# 文件夹服务阿里云 OSS 集成 **日期**:2026-02-04 **类型**:功能完善 **影响范围**:后端 - 文件夹服务(Celery 任务) --- ## 变更概述 将文件夹导出和清理任务中的对象存储集成从 TODO 状态更新为使用现有的阿里云 OSS 实现。 --- ## 变更内容 ### 1. 导出任务 OSS 上传 **文件**:`server/app/tasks/folder_export_tasks.py` **变更前**: ```python async def _upload_to_storage(zip_path: Path, folder_id: UUID) -> str: # TODO: 实际实现 MinIO 上传 # 模拟上传 time.sleep(1) file_url = f"https://cdn.example.com/exports/folders/{folder_id}.zip" return file_url ``` **变更后**: ```python async def _upload_to_storage(zip_path: Path, folder_id: UUID) -> str: """上传到对象存储(阿里云 OSS)""" from app.core.storage import StorageService # 读取 ZIP 文件内容 with open(zip_path, 'rb') as f: file_content = f.read() # 使用 StorageService 上传到 OSS storage = StorageService() object_name = f"exports/folders/{folder_id}.zip" file_url = await storage.upload_bytes( data=file_content, object_name=object_name, content_type='application/zip' ) logger.info("文件上传完成: %s", file_url) return file_url ``` **说明**: - 使用现有的 `StorageService.upload_bytes()` 方法 - 基于 boto3 S3 兼容协议,支持阿里云 OSS - 自动处理文件 URL 生成 --- ### 2. 清理任务 OSS 删除 **文件**:`server/app/tasks/folder_cleanup_tasks.py` **变更前**: ```python async def _delete_storage_file(file_url: str) -> None: # TODO: 实际实现 MinIO 删除 logger.info("删除存储文件: %s", file_url) ``` **变更后**: ```python async def _delete_storage_file(file_url: str) -> None: """删除对象存储中的文件(阿里云 OSS)""" from app.core.storage import StorageService from app.core.config import settings # 从 URL 中提取 object_name if settings.S3_PUBLIC_URL and file_url.startswith(settings.S3_PUBLIC_URL): object_name = file_url.replace(f"{settings.S3_PUBLIC_URL}/", "") else: # 兼容其他 URL 格式 parts = file_url.split('/') object_name = '/'.join(parts[-3:]) # 使用 StorageService 删除文件 storage = StorageService() await storage.delete_file(object_name) logger.info("删除存储文件: %s (object_name: %s)", file_url, object_name) ``` **说明**: - 使用现有的 `StorageService.delete_file()` 方法 - 从 URL 中提取 object_name - 支持多种 URL 格式 --- ## 技术实现 ### StorageService 架构 **位置**:`server/app/core/storage.py` **核心功能**: ```python class StorageService: """对象存储服务 - 基于 boto3 S3 兼容协议""" async def upload_bytes( self, data: bytes, object_name: str, content_type: Optional[str] = None ) -> str: """上传字节数据到对象存储""" # 使用 boto3 S3 客户端上传 # 返回公开访问 URL async def delete_file(self, object_name: str) -> None: """删除文件""" # 使用 boto3 S3 客户端删除 ``` **配置**: - `S3_ENDPOINT_URL` - 阿里云 OSS Endpoint - `S3_ACCESS_KEY_ID` - AccessKey ID - `S3_SECRET_ACCESS_KEY` - AccessKey Secret - `S3_BUCKET_NAME` - Bucket 名称 - `S3_REGION` - 区域 - `S3_PUBLIC_URL` - 公开访问 URL 前缀 --- ## 参考实现 项目中已有多处使用 `StorageService` 的实现: 1. **AI 任务文件上传**:`server/app/tasks/ai_tasks.py` - `_download_and_upload_file()` - 下载并上传文件 - `_upload_file_from_bytes()` - 从字节数据上传 2. **文件存储服务**:`server/app/services/file_storage_service.py` - `upload_file()` - 带去重的文件上传 - `cleanup_unused_files()` - 清理无引用文件 --- ## 测试验证 ### 1. 上传测试 ```python # 测试导出任务上传 from app.tasks.folder_export_tasks import process_folder_export # 创建导出任务 job_id = "..." result = process_folder_export.apply_async(args=[job_id]) # 验证文件 URL assert result.get()['file_url'].startswith(settings.S3_PUBLIC_URL) ``` ### 2. 删除测试 ```python # 测试清理任务删除 from app.tasks.folder_cleanup_tasks import cleanup_expired_exports # 运行清理任务 result = cleanup_expired_exports.apply() # 验证删除结果 assert result.get()['deleted_count'] > 0 ``` --- ## 相关文档 - [StorageService 实现](../../architecture/tech-stack.md#storage) - [文件夹服务完整实现](./2026-02-04-folder-service-complete-implementation.md) - [阿里云 OSS 配置](../../guides/oss-configuration.md) --- ## 总结 本次变更完成了文件夹服务与阿里云 OSS 的集成: 1. ✅ **导出任务上传** - 使用 `StorageService.upload_bytes()` 2. ✅ **清理任务删除** - 使用 `StorageService.delete_file()` 3. ✅ **配置复用** - 使用现有的 S3 兼容配置 4. ✅ **代码一致性** - 与项目其他模块保持一致 文件夹服务现已完全集成阿里云 OSS,可以正常处理文件导出和清理任务。