import asyncio from typing import Optional, Dict # 导入 R2 上传器 from utils.r2_uploader import get_r2_uploader, R2Config async def save_and_upload_to_r2( file, company_code: str, product_number: str, file_type: str, # 'media' 或 'cert' r2_config: Optional[R2Config] = None, sub_type: Optional[str] = None # 认证类型,如 'ce', 'rohs' 等 ) -> Dict: """ 直接上传文件到 R2(不再保存到本地) 参数: file: 上传的文件对象 company_code: 公司编码 product_number: 商品货号 file_type: 文件类型 ('media' 或 'cert') r2_config: R2 配置对象(如果为 None,则上传失败) sub_type: 子类型(认证类型) 返回: dict: { 'file_path': str, # 空字符串(保持兼容性) 'file_name': str, # 文件名 'full_path': str, # 空字符串(保持兼容性) 'server_url': str, # 空字符串(保持兼容性) 'r2_url': str, # R2 原图 URL(media_url 字段使用) 'thumbnail_url': str, # R2 缩略图 URL(thumbnail_path 字段使用) 'r2_key': str, # R2 对象键 'thumbnail_key': str # R2 缩略图对象键 } """ # 读取文件内容 if hasattr(file, 'file'): # UploadFile 对象,file.file 是 SpooledTemporaryFile file_content = file.file.read() else: # 其他文件对象 file_content = file.read() # 获取原始文件名 original_filename = getattr(file, 'filename', 'unknown') # 尝试上传到 R2 r2_url = '' thumbnail_url = '' r2_key = '' thumbnail_key = '' if r2_config: r2_uploader = get_r2_uploader() if r2_uploader.is_available(r2_config): try: r2_result = await r2_uploader.upload_file( file_buffer=file_content, company_code=company_code, product_number=product_number, file_type=file_type, filename=original_filename, config=r2_config, sub_type=sub_type, generate_thumbnail=(file_type == 'media') ) r2_url = r2_result['r2_url'] thumbnail_url = r2_result['thumbnail_url'] r2_key = r2_result['r2_key'] thumbnail_key = r2_result['thumbnail_key'] except Exception as e: print(f"R2 上传失败: {e}") raise else: print("R2 配置未提供,上传失败") raise ValueError("R2 配置未提供") return { 'file_path': '', 'file_name': original_filename, 'full_path': '', 'server_url': '', 'r2_url': r2_url, 'thumbnail_url': thumbnail_url, 'r2_key': r2_key, 'thumbnail_key': thumbnail_key }