From 78f3f91abb48ff0b852b634be84c6dfd590a942e Mon Sep 17 00:00:00 2001 From: aaron <> Date: Mon, 20 Jan 2025 12:51:09 +0800 Subject: [PATCH] update --- app/api/endpoints/upload.py | 22 +++++++++++-- app/core/cos.py | 66 +++++++++++++++++++++++++++++++++---- requirements.txt | 1 + 3 files changed, 80 insertions(+), 9 deletions(-) diff --git a/app/api/endpoints/upload.py b/app/api/endpoints/upload.py index 4a7e702..fc89ab4 100644 --- a/app/api/endpoints/upload.py +++ b/app/api/endpoints/upload.py @@ -2,7 +2,7 @@ from fastapi import APIRouter, UploadFile, File, Depends from typing import List import uuid from datetime import datetime -from app.core.cos import cos_client +from app.core.cos import cos_manager from app.core.config import settings from app.models.upload import UploadResponse, MultiUploadResponse from app.core.response import success_response, error_response, ResponseModel @@ -18,7 +18,7 @@ async def upload_to_cos(file: UploadFile) -> str: filename = f"{datetime.now().strftime('%Y%m%d')}/{uuid.uuid4()}.{ext}" # 上传文件 - cos_client.put_object( + cos_manager.put_object( Bucket=settings.COS_BUCKET, Body=await file.read(), Key=filename, @@ -62,4 +62,20 @@ async def upload_images( urls.append(url) return success_response(data=MultiUploadResponse(urls=urls)) except Exception as e: - return error_response(code=500, message=f"上传失败: {str(e)}") \ No newline at end of file + return error_response(code=500, message=f"上传失败: {str(e)}") + +@router.get("/presigned-url") +async def get_presigned_url( + filename: str, + current_user: UserDB = Depends(get_current_user) +): + """获取预签名上传URL""" + key = f"uploads/{current_user.userid}/{filename}" + try: + url = cos_manager.get_upload_url(key) + return success_response(data={ + "url": url, + "key": key + }) + except Exception as e: + return error_response(code=500, message=f"获取上传URL失败: {str(e)}") \ No newline at end of file diff --git a/app/core/cos.py b/app/core/cos.py index 6dfb0a9..ab2cf34 100644 --- a/app/core/cos.py +++ b/app/core/cos.py @@ -6,10 +6,64 @@ import logging # 正常情况日志级别使用INFO,需要定位时可以修改为DEBUG,此时SDK会打印和服务端的通信信息 logging.basicConfig(level=logging.INFO, stream=sys.stdout) -cos_config = CosConfig( - Region=settings.COS_REGION, - SecretId=settings.TENCENT_SECRET_ID, - SecretKey=settings.TENCENT_SECRET_KEY -) +class COSManager: + def __init__(self): + config = CosConfig( + Region=settings.COS_REGION, + SecretId=settings.TENCENT_SECRET_ID, + SecretKey=settings.TENCENT_SECRET_KEY + ) + self.client = CosS3Client(config) + + def get_upload_url(self, key: str, expires: int = 3600) -> str: + """ + 获取预签名上传URL + + Args: + key: 对象键 + expires: 签名有效期(秒) + + Returns: + 预签名URL + """ + try: + url = self.client.get_presigned_url( + Method='PUT', + Bucket=settings.COS_BUCKET, + Key=key, + Expired=expires + ) + return url + except Exception as e: + logging.error(f"获取上传URL失败: {str(e)}") + raise + + def get_download_url(self, key: str, expires: int = 3600) -> str: + """ + 获取预签名下载URL + + Args: + key: 对象键 + expires: 签名有效期(秒) + + Returns: + 预签名URL + """ + try: + url = self.client.get_presigned_url( + Method='GET', + Bucket=settings.COS_BUCKET, + Key=key, + Expired=expires + ) + return url + except Exception as e: + logging.error(f"获取下载URL失败: {str(e)}") + raise + + def put_object(self, **kwargs): + """上传对象的封装方法""" + return self.client.put_object(**kwargs) -cos_client = CosS3Client(cos_config) \ No newline at end of file +# 创建全局 COS 客户端实例 +cos_manager = COSManager() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 3001352..4403c45 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ redis==5.0.1 pymysql==1.1.0 SQLAlchemy==2.0.27 tencentcloud-sdk-python==3.0.1035 +cos-python-sdk-v5 bcrypt aiohttp==3.9.1 cryptography==42.0.2 \ No newline at end of file