Files
NetworkDeviceManagementSystem/backend/storage/storage_service.py
QuangMinh_123 2683cdb882 Device
2026-05-27 13:50:27 +07:00

141 lines
3.5 KiB
Python

import re
import uuid
from werkzeug.utils import secure_filename
from storage.s3_client import (
get_s3_client,
get_bucket_name,
get_public_url,
)
from storage.validators import validate_image_file
def slugify(text):
"""
Chuyển text thành dạng an toàn để dùng trong tên file.
Ví dụ:
- "Router" -> "router"
- "Core Switch 01" -> "core-switch-01"
- "Thiết bị định tuyến" -> "thi-t-b-nh-tuy-n"
Lưu ý:
Hàm này đơn giản, chưa xử lý tiếng Việt hoàn hảo.
Nếu muốn slug tiếng Việt đẹp hơn, sau này có thể dùng thư viện python-slugify.
"""
if text is None or text.strip() == "":
return "file"
text = text.lower().strip()
# Thay toàn bộ ký tự không phải chữ/số bằng dấu gạch ngang.
text = re.sub(r"[^a-z0-9]+", "-", text)
# Xóa dấu gạch ngang thừa ở đầu/cuối.
text = text.strip("-")
return text or "file"
def build_object_key(folder, business_name, extension):
"""
Tạo object key để lưu file trong bucket.
MinIO/S3 không có folder thật như filesystem.
Folder ở đây chỉ là prefix trong object key.
Ví dụ:
folder = "device-types"
business_name = "Router"
extension = "svg"
Kết quả:
device-types/router-550e8400.svg
Dùng UUID để tránh trùng tên file.
"""
safe_name = slugify(business_name)
unique_id = uuid.uuid4()
return f"{folder}/{safe_name}-{unique_id}.{extension}"
def upload_image(file, folder, business_name): # Hàm Upload dùng chung cho device_types và devices
"""
Upload một file ảnh lên MinIO/S3 và trả về public URL.
Tham số:
- file: file lấy từ request.files
- folder: nhóm lưu trữ, ví dụ "device-types" hoặc "devices"
- business_name: tên nghiệp vụ để đặt tên file đẹp hơn
Ví dụ:
+ DeviceType name = Router
+ Device name = Switch tầng 2
Flow:
1. Validate file
2. Tạo object key
3. Upload file lên bucket
4. Trả về URL public để lưu vào database
"""
extension = validate_image_file(file)
object_key = build_object_key(
folder=folder,
business_name=business_name,
extension=extension,
)
s3_client = get_s3_client()
bucket_name = get_bucket_name()
public_url = get_public_url()
s3_client.upload_fileobj(
file,
bucket_name,
object_key,
ExtraArgs={
"ContentType": file.content_type
},
)
return f"{public_url}/{bucket_name}/{object_key}"
def upload_device_type_icon(file, device_type_name):
"""
Upload icon cho DeviceType.
File sẽ được lưu trong bucket với prefix:
device-types/
Ví dụ URL:
http://localhost:9000/ndms/device-types/router-uuid.svg
"""
return upload_image( # Ở đoạn này có thể trả về một hàm luôn á ? Mà không cần phải gọi hàm đó vào bên trong và truyền tham số à ?
file=file,
folder="device-types",
business_name=device_type_name,
)
def upload_device_avatar(file, device_name):
"""
Upload avatar cho Device.
File sẽ được lưu trong bucket với prefix:
devices/
Ví dụ URL:
http://localhost:9000/ndms/devices/switch-tang-2-uuid.png
"""
return upload_image(
file=file,
folder="devices",
business_name=device_name,
)