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.
3.6 KiB
3.6 KiB
修复项目素材 API 文件 URL 返回问题
日期: 2026-02-12
类型: Bug 修复
影响范围: 后端 API - 项目素材模块
问题描述
/api/v1/projects/{project_id}/resources 接口上传 footage(实拍)素材后,返回的 fileUrl 和 thumbnailUrl 字段为相对路径(如 project_resource_footage/xxx.mp4),而非完整的访问 URL(如 https://oss.example.com/project_resource_footage/xxx.mp4)。
前端无法直接使用相对路径访问文件,导致素材预览失败。
根因分析
ProjectResourceResponseSchema 直接返回数据库存储的相对路径- 未使用
build_file_url()函数转换为完整 URL - 其他模块(如
ScreenplayResponse、AttachmentResponse)已使用@computed_field自动转换
解决方案
在 ProjectResourceResponse Schema 中添加 @computed_field,自动将相对路径转换为完整 URL:
from pydantic import computed_field
from app.core.storage import build_file_url
class ProjectResourceResponse(BaseModel):
# 内部字段存储相对路径
file_url: str = Field(..., description="文件相对路径(内部使用)")
thumbnail_url: Optional[str] = Field(None, description="缩略图相对路径(内部使用)")
# 计算字段返回完整 URL
@computed_field(alias="fileUrl")
@property
def full_file_url(self) -> str:
"""动态生成完整文件访问 URL"""
return build_file_url(self.file_url)
@computed_field(alias="thumbnailUrl")
@property
def full_thumbnail_url(self) -> Optional[str]:
"""动态生成完整缩略图访问 URL"""
return build_file_url(self.thumbnail_url) if self.thumbnail_url else None
技术细节
修改文件
server/app/schemas/project_resource.py
工作原理
- 数据库存储相对路径(便于域名变更和多环境部署)
- Schema 序列化时自动调用
build_file_url()转换为完整 URL - API 响应中
fileUrl和thumbnailUrl字段返回完整 URL
优势
- 统一模式: 与
ScreenplayResponse、AttachmentResponse保持一致 - 自动转换: 所有使用该 Schema 的接口自动生效
- 易维护: 域名变更时只需修改配置,无需改代码
影响范围
受影响接口
POST /api/v1/projects/{project_id}/resources- 上传素材GET /api/v1/resources/{resource_id}- 获取素材详情PATCH /api/v1/resources/{resource_id}- 更新素材GET /api/v1/projects/{project_id}/resources- 获取项目素材列表GET /api/v1/projects/{project_id}/resources?element_tag_id={tag_id}- 获取标签素材列表
兼容性
- ✅ 向后兼容:前端已期望接收完整 URL
- ✅ 无需数据迁移:数据库继续存储相对路径
- ✅ 无需前端改动:返回格式符合前端预期
验证方法
# 1. 上传 footage 素材
curl -X POST "http://localhost:8000/api/v1/projects/{project_id}/resources" \
-H "Authorization: Bearer {token}" \
-F "file=@test.mp4" \
-F "name=测试视频" \
-F "type=footage"
# 2. 检查响应中的 fileUrl 字段
# ✅ 正确: "fileUrl": "https://oss.example.com/project_resource_footage/xxx.mp4"
# ❌ 错误: "fileUrl": "project_resource_footage/xxx.mp4"
相关文件
- Schema:
server/app/schemas/project_resource.py - API:
server/app/api/v1/project_resources.py - 工具函数:
server/app/core/storage.py(build_file_url)
参考
- 类似实现:
server/app/schemas/screenplay.py(ScreenplayResponse) - 类似实现:
server/app/schemas/attachment.py(AttachmentResponse)