# AI Service 集成 FileStorageService **日期**: 2026-01-30 **类型**: Feature Enhancement **影响范围**: AI Service, AI Tasks, File Storage **关联文档**: `docs/requirements/backend/04-services/ai/ai-service.md` ## 变更概述 为 AI 生成任务集成 FileStorageService,实现 AI 生成文件的自动下载和上传到自有对象存储(MinIO/OSS),解决 AI 提供商临时 URL 时效性问题,确保数据主权和文件持久化。 ## 变更动机 ### 问题 1. **临时 URL 时效性**:AI 提供商(如 OpenAI)返回的文件 URL 通常只有 1 小时有效期 2. **数据主权缺失**:生成的内容存储在第三方服务器,无法完全控制 3. **无法去重**:重复生成相同内容时无法利用已有文件 4. **引用计数缺失**:无法追踪文件被哪些资源引用 ### 解决方案 - 在每个 AI 生成任务完成后,自动下载文件并上传到 FileStorageService - 利用 SHA256 校验和实现文件去重 - 使用引用计数管理文件生命周期 - 支持 MinIO(开发环境)和云 OSS(生产环境)无缝切换 ## 技术实现 ### 1. 新增依赖 在 `ai_tasks.py` 中添加: ```python import httpx # 用于下载 AI 生成的文件 from app.services.file_storage_service import FileStorageService ``` ### 2. 新增辅助函数 #### `_download_and_upload_file()` ```python async def _download_and_upload_file( file_url: str, filename: str, content_type: str, category: str, user_id: str ) -> Dict[str, Any] ``` **功能**: 1. 使用 `httpx.AsyncClient` 下载 AI 提供商返回的文件 2. 调用 `FileStorageService.upload_file()` 上传到自有 OSS 3. 返回文件元数据(包含自有 URL、校验和、文件大小等) **超时设置**:300 秒(5 分钟),适配大文件下载 ### 3. 更新所有生成任务 为以下 5 个任务添加文件上传逻辑: #### 图片生成任务 (`generate_image_task`) - **进度**: 30% → 70% → 100% - **文件类型**: `image/png` - **存储路径**: `ai-generated/images/` - **文件名**: `image_{job_id}.png` #### 视频生成任务 (`generate_video_task`) - **进度**: 30% → 70% → 100% - **文件类型**: `video/mp4` - **存储路径**: `ai-generated/videos/` - **文件名**: `video_{job_id}.mp4` #### 音效生成任务 (`generate_sound_task`) - **进度**: 30% → 70% → 100% - **文件类型**: `audio/mpeg` - **存储路径**: `ai-generated/sounds/` - **文件名**: `sound_{job_id}.mp3` #### 配音生成任务 (`generate_voice_task`) - **进度**: 30% → 70% → 100% - **文件类型**: `audio/mpeg` - **存储路径**: `ai-generated/voices/` - **文件名**: `voice_{job_id}.mp3` #### 字幕生成任务 (`generate_subtitle_task`) - **进度**: 30% → 70% → 100% - **文件类型**: `text/plain` - **存储路径**: `ai-generated/subtitles/` - **文件名**: `subtitle_{job_id}.srt` #### 文本处理任务 (`process_text_task`) - **进度**: 30% → 70% → 100% - **文件类型**: `text/plain` - **存储路径**: `ai-generated/texts/` - **文件名**: `text_{job_id}.txt` - **说明**: 文本处理任务通常不返回文件,但为了完整性也添加了处理逻辑 ### 4. 输出数据格式 更新后的 `output_data` 包含以下字段: ```json { "file_url": "https://minio.example.com/ai-generated/images/xxx.png", "file_size": 1024000, "checksum": "abc123...", "mime_type": "image/png", "storage_provider": "minio", "storage_path": "ai-generated/images/user_id/checksum.png", "original_url": "https://openai.com/temp/xxx.png" } ``` **字段说明**: - `file_url`: 自有 OSS URL(永久有效) - `file_size`: 文件大小(字节) - `checksum`: SHA256 校验和(用于去重) - `mime_type`: MIME 类型 - `storage_provider`: 存储提供商(minio/oss) - `storage_path`: 对象存储路径 - `original_url`: AI 提供商原始 URL(保留用于调试) ### 5. 日志格式修复 将所有日志从 f-string 格式改为 %-formatting: ```python # ❌ 错误 logger.info(f"任务完成: job_id={job_id}") # ✅ 正确 logger.info("任务完成: job_id=%s", job_id) ``` ## 文件修改清单 ### 修改文件 - `server/app/tasks/ai_tasks.py` - 添加 `httpx` 导入 - 添加 `FileStorageService` 导入 - 新增 `_download_and_upload_file()` 函数 - 更新 6 个生成任务的文件上传逻辑 - 修复所有日志格式为 %-formatting ### 新增文件 - `docs/server/changelogs/2026-01-30-ai-service-file-storage-integration.md` ## 测试建议 ### 单元测试 ```python # 测试文件下载和上传 async def test_download_and_upload_file(): # Mock httpx.AsyncClient # Mock FileStorageService # 验证文件元数据 pass ``` ### 集成测试 ```python # 测试完整的图片生成流程 async def test_generate_image_with_file_storage(async_client, test_auth): # 1. 调用图片生成 API # 2. 等待任务完成 # 3. 验证 output_data 包含 file_url # 4. 验证文件可以访问 # 5. 验证 file_checksum 表有记录 pass ``` ### 手动测试 ```bash # 1. 启动服务 docker-compose up -d # 2. 调用图片生成 API curl -X POST http://localhost:8000/api/v1/ai/generate/image \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "prompt": "A beautiful sunset", "width": 1024, "height": 1024 }' # 3. 查询任务状态 curl http://localhost:8000/api/v1/ai/jobs/{job_id} \ -H "Authorization: Bearer $TOKEN" # 4. 验证 MinIO 中是否有文件 # 访问 http://localhost:9001 (MinIO Console) # 用户名: minioadmin, 密码: minioadmin ``` ## 环境配置 ### 开发环境(MinIO) ```env STORAGE_PROVIDER=minio MINIO_ENDPOINT=minio:9000 MINIO_ACCESS_KEY=minioadmin MINIO_SECRET_KEY=minioadmin MINIO_BUCKET=jointo MINIO_SECURE=false ``` ### 生产环境(阿里云 OSS) ```env STORAGE_PROVIDER=oss OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com OSS_ACCESS_KEY_ID=your_access_key OSS_ACCESS_KEY_SECRET=your_secret_key OSS_BUCKET=jointo-prod ``` ## 性能考虑 ### 下载超时 - 设置 300 秒超时,适配大文件(如 4K 视频) - 如果下载失败,任务会自动重试(最多 3 次) ### 文件去重 - 使用 SHA256 校验和去重,避免重复存储 - 相同内容的文件只存储一次,节省存储空间 ### 引用计数 - 每次使用文件时增加引用计数 - 删除资源时减少引用计数 - 引用计数为 0 时自动删除文件 ## 后续优化 ### 短期(1-2 周) 1. 添加文件压缩(图片、视频) 2. 添加缩略图生成(图片、视频) 3. 添加文件格式转换(如 PNG → WebP) ### 中期(1-2 月) 1. 实现 CDN 加速 2. 添加文件访问统计 3. 实现文件分级存储(热数据/冷数据) ### 长期(3-6 月) 1. 实现多云存储(阿里云 + 腾讯云) 2. 添加文件加密存储 3. 实现文件版本管理 ## 风险与注意事项 ### 风险 1. **下载失败**:AI 提供商 URL 可能失效或网络不稳定 - **缓解措施**:设置重试机制(最多 3 次) 2. **存储空间不足**:大量生成文件可能占用大量存储 - **缓解措施**:定期清理无引用文件(30 天) 3. **并发冲突**:多个任务同时上传相同文件 - **缓解措施**:使用校验和去重,数据库唯一约束 ### 注意事项 1. 确保 MinIO/OSS 服务正常运行 2. 确保网络可以访问 AI 提供商的文件 URL 3. 监控存储空间使用情况 4. 定期备份重要文件 ## 相关文档 - [AI Service 设计文档](../requirements/backend/04-services/ai/ai-service.md) - [File Storage Service 设计文档](../requirements/backend/04-services/resource/file-storage-service.md) - [测试规范](../../.claude/skills/jointo-tech-stack/references/testing.md) ## 总结 此次集成完成了 AI Service 与 FileStorageService 的深度整合,实现了: - ✅ AI 生成文件自动下载和上传 - ✅ 文件去重和引用计数 - ✅ 支持 MinIO 和云 OSS - ✅ 完整的错误处理和重试机制 - ✅ 符合 jointo-tech-stack 规范 所有 AI 生成的文件现在都会永久存储在自有系统中,解决了临时 URL 时效性问题,确保了数据主权和文件持久化。