# Changelog: 分镜图片上传功能 **日期**: 2026-02-12 **类型**: Feature **影响范围**: 分镜资源管理 ## 概述 实现分镜图片上传接口,支持用户直接上传图片到 `storyboard_images` 表,无需依赖 AI 生成。 ## 变更内容 ### 1. Service 层 **文件**: `server/app/services/storyboard_resource_service.py` 新增方法: - `upload_image()` - 处理分镜图片上传逻辑 **功能特性**: - 支持图片格式:JPEG、PNG、GIF、WebP、BMP - 文件大小限制:最大 20MB - 自动计算 SHA256 校验和 - 自动获取图片宽高 - 自动生成版本号(递增) - 名称自动生成:`{镜号}-{分镜标题}-方案{编号}` - 首张图片自动激活 **存储路径**: ``` storyboard_images/source/{year}/{month}/{day}/{checksum}.{ext} ``` ### 2. API 层 **文件**: `server/app/api/v1/storyboard_resources.py` 新增接口: ``` POST /api/v1/storyboard-resources/storyboards/{storyboard_id}/images/upload ``` **请求参数**: - `file` (required): 图片文件 - `name` (optional): 图片名称(不提供则自动生成) - `description` (optional): 图片描述 **响应**: - 状态码:201 Created - 返回:`ImageResponse` 对象 ### 3. 测试 **文件**: `server/tests/integration/test_storyboard_resource_api.py` 新增测试用例: - `test_upload_storyboard_image_success` - 正常上传 - `test_upload_storyboard_image_auto_name` - 自动生成名称 - `test_upload_storyboard_image_invalid_type` - 文件类型验证 - `test_upload_storyboard_image_too_large` - 文件大小限制 - `test_upload_storyboard_image_no_permission` - 权限验证 ## 技术实现 ### 文件上传流程 ``` 1. 验证权限(editor 角色) 2. 验证文件类型和大小 3. 读取文件内容 4. 解析图片元数据(宽高、格式) 5. 计算 SHA256 校验和 6. 上传到对象存储(StorageService) 7. 创建 storyboard_images 记录 8. 返回响应 ``` ### 与 AI 生成的区别 | 特性 | AI 生成 (`create_image`) | 用户上传 (`upload_image`) | |------|-------------------------|--------------------------| | 触发方式 | AI 任务完成后调用 | 用户直接上传 | | 文件来源 | AI 生成的 URL | 用户上传的文件 | | 去重逻辑 | 使用 `FileStorageService` | 直接上传到对象存储 | | 状态 | 可能是 PENDING/PROCESSING | 直接 COMPLETED | | AI 参数 | 包含 ai_model, ai_prompt 等 | 无 AI 参数 | ### 不使用 FileStorageService 的原因 1. **简化实现**:分镜图片通常不会重复上传 2. **保持一致**:与现有 `create_image()` 方法保持一致 3. **减少依赖**:避免不必要的 `file_checksums` 表依赖 ## 使用示例 ### cURL 示例 ```bash curl -X POST \ "http://localhost:8000/api/v1/storyboard-resources/storyboards/{storyboard_id}/images/upload" \ -H "Authorization: Bearer {token}" \ -F "file=@image.png" \ -F "name=开场镜头" \ -F "description=主角登场的第一个镜头" ``` ### Python 示例 ```python import httpx async with httpx.AsyncClient() as client: with open('image.png', 'rb') as f: response = await client.post( f"/api/v1/storyboard-resources/storyboards/{storyboard_id}/images/upload", files={'file': ('image.png', f, 'image/png')}, data={ 'name': '开场镜头', 'description': '主角登场的第一个镜头' }, headers={'Authorization': f'Bearer {token}'} ) ``` ## 验证步骤 1. 启动服务 2. 运行集成测试: ```bash docker exec jointo-server-app pytest server/tests/integration/test_storyboard_resource_api.py::TestStoryboardResourceAPI::test_upload_storyboard_image_success -v ``` 3. 验证文件已上传到对象存储 4. 验证数据库记录已创建 ## 后续优化 1. 添加缩略图生成功能 2. 支持批量上传 3. 添加图片压缩功能 4. 支持拖拽上传(前端) ## 相关文件 - `server/app/services/storyboard_resource_service.py` - `server/app/api/v1/storyboard_resources.py` - `server/tests/integration/test_storyboard_resource_api.py` - `server/app/models/storyboard_resource.py` - `server/app/schemas/storyboard_resource.py`