You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

4.1 KiB

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 示例

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 示例

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. 运行集成测试:
    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