2026-02-02 09:40:02 +08:00
|
|
|
|
import uuid
|
|
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
|
|
from typing import Optional
|
2026-02-05 13:57:49 +08:00
|
|
|
|
from pathlib import Path
|
2026-02-02 09:40:02 +08:00
|
|
|
|
|
2026-02-05 13:57:49 +08:00
|
|
|
|
# import oss2 # TODO: 阿里云 OSS 待配置完成后启用
|
2026-02-02 09:40:02 +08:00
|
|
|
|
from app.config import settings
|
|
|
|
|
|
from app.utils.logger import logger
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OSSStorage:
|
2026-02-05 13:57:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
图片存储类
|
|
|
|
|
|
TODO: 阿里云 OSS 配置完成后,注释掉 use_local_only=True 即可启用 OSS
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, use_local_only: bool = True):
|
|
|
|
|
|
self.use_local_only = use_local_only
|
2026-02-02 09:40:02 +08:00
|
|
|
|
self.bucket = None
|
2026-02-05 13:57:49 +08:00
|
|
|
|
|
|
|
|
|
|
if not self.use_local_only:
|
|
|
|
|
|
self._init_bucket()
|
2026-02-02 09:40:02 +08:00
|
|
|
|
|
|
|
|
|
|
def _init_bucket(self):
|
2026-02-05 13:57:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
初始化 OSS Bucket(待配置完成后启用)
|
|
|
|
|
|
"""
|
|
|
|
|
|
# TODO: 阿里云 OSS 配置完成后启用以下代码
|
|
|
|
|
|
# if not settings.oss.access_key_id or not settings.oss.bucket_name:
|
|
|
|
|
|
# logger.warning("OSS配置不完整,将使用本地存储")
|
|
|
|
|
|
# self.use_local_only = True
|
|
|
|
|
|
# return
|
|
|
|
|
|
#
|
|
|
|
|
|
# try:
|
|
|
|
|
|
# auth = oss2.Auth(settings.oss.access_key_id, settings.oss.access_key_secret)
|
|
|
|
|
|
# self.bucket = oss2.Bucket(auth, settings.oss.endpoint, settings.oss.bucket_name)
|
|
|
|
|
|
# logger.info(f"OSS连接成功: {settings.oss.bucket_name}")
|
|
|
|
|
|
# except Exception as e:
|
|
|
|
|
|
# logger.error(f"OSS连接失败: {e}")
|
|
|
|
|
|
# self.bucket = None
|
|
|
|
|
|
logger.info("OSS存储已注释,启用本地存储模式")
|
2026-02-02 09:40:02 +08:00
|
|
|
|
|
|
|
|
|
|
def upload_image(self, image_data: bytes, filename: Optional[str] = None) -> str:
|
2026-02-05 13:57:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
上传图片(当前使用本地存储,OSS 配置完成后可启用)
|
|
|
|
|
|
"""
|
|
|
|
|
|
if self.use_local_only or not self.bucket:
|
2026-02-02 09:40:02 +08:00
|
|
|
|
return self._upload_local(image_data, filename)
|
|
|
|
|
|
|
2026-02-05 13:57:49 +08:00
|
|
|
|
# TODO: 阿里云 OSS 配置完成后启用以下代码
|
|
|
|
|
|
# if not self.bucket:
|
|
|
|
|
|
# return self._upload_local(image_data, filename)
|
|
|
|
|
|
#
|
|
|
|
|
|
# if filename is None:
|
|
|
|
|
|
# timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
|
|
|
|
# unique_id = uuid.uuid4().hex[:8]
|
|
|
|
|
|
# ext = ".jpg"
|
|
|
|
|
|
# filename = f"alerts/{timestamp}_{unique_id}{ext}"
|
|
|
|
|
|
#
|
|
|
|
|
|
# try:
|
|
|
|
|
|
# self.bucket.put_object(filename, image_data)
|
|
|
|
|
|
# url = f"{settings.oss.url_prefix}/{filename}"
|
|
|
|
|
|
# logger.info(f"图片上传OSS成功: {url}")
|
|
|
|
|
|
# return url
|
|
|
|
|
|
# except Exception as e:
|
|
|
|
|
|
# logger.error(f"图片上传OSS失败: {e}")
|
|
|
|
|
|
# return self._upload_local(image_data, filename)
|
|
|
|
|
|
|
|
|
|
|
|
return self._upload_local(image_data, filename)
|
2026-02-02 09:40:02 +08:00
|
|
|
|
|
|
|
|
|
|
def _upload_local(self, image_data: bytes, filename: Optional[str] = None) -> str:
|
2026-02-05 13:57:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
本地存储(当前使用)
|
|
|
|
|
|
"""
|
2026-02-02 09:40:02 +08:00
|
|
|
|
upload_dir = Path("uploads")
|
|
|
|
|
|
upload_dir.mkdir(exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
if filename is None:
|
|
|
|
|
|
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
|
|
|
|
unique_id = uuid.uuid4().hex[:8]
|
|
|
|
|
|
filename = f"alerts/{timestamp}_{unique_id}.jpg"
|
|
|
|
|
|
|
|
|
|
|
|
file_path = upload_dir / filename
|
|
|
|
|
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
with open(file_path, "wb") as f:
|
|
|
|
|
|
f.write(image_data)
|
|
|
|
|
|
|
|
|
|
|
|
local_url = f"/uploads/{filename}"
|
|
|
|
|
|
logger.info(f"图片保存本地: {local_url}")
|
|
|
|
|
|
return local_url
|
|
|
|
|
|
|
|
|
|
|
|
def get_url(self, path: str) -> str:
|
2026-02-05 13:57:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
获取图片访问URL
|
|
|
|
|
|
"""
|
2026-02-02 09:40:02 +08:00
|
|
|
|
if path.startswith("http"):
|
|
|
|
|
|
return path
|
2026-02-05 13:57:49 +08:00
|
|
|
|
# TODO: 阿里云 OSS 配置完成后启用以下代码
|
|
|
|
|
|
# if self.bucket:
|
|
|
|
|
|
# return f"{settings.oss.url_prefix}/{path}"
|
2026-02-02 09:40:02 +08:00
|
|
|
|
return f"/uploads/{path}" if not path.startswith("/") else path
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-02-05 13:57:49 +08:00
|
|
|
|
# 使用本地存储模式(OSS 配置完成后可修改为 OSSStorage(use_local_only=False))
|
|
|
|
|
|
oss_storage = OSSStorage(use_local_only=True)
|
2026-02-02 09:40:02 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_oss_storage() -> OSSStorage:
|
|
|
|
|
|
return oss_storage
|