Files
character-roleplay-backend/app/utils/s3.py
T

53 lines
2.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import oss2
import httpx
import os
from dotenv import load_dotenv
load_dotenv()
# 加载配置
ACCESS_KEY_ID = os.getenv("S3_ACCESS_KEY_ID")
ACCESS_KEY_SECRET = os.getenv("S3_SECRET_ACCESS_KEY")
ENDPOINT = os.getenv("S3_ENDPOINT", "https://oss-ap-northeast-1.aliyuncs.com")
BUCKET_NAME = os.getenv("S3_STORAGE_BUCKET_NAME", "character-roleplay-dev-asset")
# 初始化阿里云 Auth 和 Bucket
auth = oss2.Auth(ACCESS_KEY_ID, ACCESS_KEY_SECRET)
bucket = oss2.Bucket(auth, ENDPOINT, BUCKET_NAME)
async def upload_google_avatar_to_s3(google_avatar_url: str, user_id: str) -> str:
"""
下载 Google 头像并上传到阿里云 OSS
"""
try:
# 1. 使用 httpx 下载图片
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(google_avatar_url)
if response.status_code != 200:
return google_avatar_url
image_data = response.content
# 获取内容类型(如 image/jpeg
content_type = response.headers.get("Content-Type", "image/jpeg")
# 构造 OSS 中的存储路径
object_name = f"avatars/{user_id}/avatar.jpg"
headers = {"Content-Type": content_type}
# oss2.Bucket.put_object 是同步阻塞调用
# 在高并发下建议使用 run_in_executor,初期可以直接这样写
bucket.put_object(object_name, image_data, headers=headers)
# 不直接返回公开访问的 URL,而是返回 OSS 内部相对路径,前端可以通过 CDN 或后端代理访问
# 这样可以支持后续更换存储服务,以及更换 OSS_BASE_URL 域名而不影响前端
# host = ENDPOINT.replace("https://", "")
# oss_url = f"https://{BUCKET_NAME}.{host}/{object_name}"
# return oss_url
return object_name
except Exception as e:
# 打印错误日志,生产环境建议使用 logger
print(f"OSS Upload Error: {str(e)}")
# 降级处理:上传失败则返回原始 Google URL,确保用户能注册成功
return google_avatar_url