Skip to content

用户素材上传 ​

本接口用于将本地图片 / 视频 / 音频上传至 iModelSpace COS,并自动登记至素材库。 登记后的素材可用于 POST /v1/videos/generations 请求体的 image / video 字段(参考图 / 参考视频)。

全链路鉴权方式为 Authorization: Bearer sk-xxx(亦支持 x-api-key 请求头), 不依赖浏览器登录态,适配 OpenAI / Anthropic SDK 调用场景。

端点索引 ​

步骤方法路径用途
1POST/v1/files/upload_cos_signer申请 COS 直传预签名 URL 与 file_key,同步登记占位素材记录(status=uploading)
2PUT<presigned_url>将文件二进制流直接上传至腾讯云 COS
3POST/v1/files/upload_cos_confirm通过 file_key 触发 COS HeadObject 元数据核对,完成登记并返回完整素材对象

状态机说明(2026-08-30 新增) ​

第一步登记          第三步成功           重复 confirm
uploading  ───►  active  ───►  active (幂等,直接返回原对象)
   │
   └──►  failed  ◄───  第三步 HeadObject 失败(允许重新走第一步)

disabled 由管理员手动置位,与上传流程无关。

完整上传流程 ​

第一步:申请预签名并登记占位素材 ​

http
POST https://api.imodel.space/v1/files/upload_cos_signer
Authorization: Bearer {key}
Content-Type: application/json

{
  "file_suffix": "jpg"
}

请求参数 ​

字段是否必填说明
file_suffix是不带点的扩展名。支持 jpg / jpeg / png / gif / bmp / webp / mp4 / mov / avi / webm / mp3 / wav / flac / aac

响应参数 ​

仅展示第二步与第三步所需的字段:

json
{
  "presigned_url": "https://imodel-1387889447.cos.ap-shanghai.myqcloud.com/users/0_1000/9/images/20260828153000_xxx.jpg?sign=...",
  "file_key":      "users/0_1000/9/images/20260828153000_xxx.jpg"
}
字段用途
presigned_url第二步用:将文件 PUT 至该 URL,有效期由 configs.Tencent.Cos.Duration 控制(默认 60 秒)
file_key第三步用:原样透传至 /v1/files/upload_cos_confirm

第二步:上传文件至 COS ​

请求 URL ​

直接使用第一步返回的 presigned_url,禁止对其中的 path、query 或 sign= 参数进行任何修改。 示例(完整 URL,含 sign= 参数):

https://imodel-1387889447.cos.ap-shanghai.myqcloud.com/users/0_1000/9/images/20260828153000_xxx.jpg?sign=...

请求构造 ​

HTTP 字段取值
方法PUT(必填)
请求体文件原始字节流(二进制,非 JSON,非 form-data)
Content-Type可省略;若填写,须与实际文件类型一致(image/jpeg 等)。COS 服务端亦会自行推断
鉴权头禁止添加 Authorization / x-api-key 等任何鉴权头,COS 鉴权信息已编码于 URL query string

典型实现示例:

客户端请求构造
curlcurl -X PUT --upload-file ./cat.jpg "<presigned_url>"
浏览器 fetchfetch(presignedUrl, { method: 'PUT', body: file })
Python requestsrequests.put(presignedUrl, data=open('./cat.jpg','rb').read())

响应处理 ​

HTTP 状态码含义客户端处理
200 OK上传成功进入第三步 confirm
204 No Content上传成功(部分 COS 区域使用此状态码)进入第三步 confirm
403 SignatureDoesNotMatch预签名过期或被篡改重新调用第一步获取新预签名
403 AccessDeniedSTS 策略拒绝(超出 prefix 边界)检查 file_key 是否位于 users/{group}/{uid}/ 子树
404 NoSuchKey桶或对象键不存在桶配置异常,请联系管理员
4xx / 5xx 其他COS 标准错误解析响应体中的 <Code> / <Message> 字段

成功响应体为空。失败响应体为 XML 格式,示例:

xml
<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>SignatureDoesNotMatch</Code>
  <Message>The provided signature does not match...</Message>
  <RequestId>xxx</RequestId>
</Error>

第三步:确认上传并完成登记 ​

http
POST https://api.imodel.space/v1/files/upload_cos_confirm
Authorization: Bearer {key}
Content-Type: application/json

{
  "file_key": "users/0_1000/9/images/20260828153000_xxx.jpg"
}

请求参数 ​

字段是否必填说明
file_key是第一步响应中的 file_key,原样透传

处理流程 ​

  1. 所有者校验:file_key 必须以 users/{group}/{uid}/ 起始,防止越权登记他人素材。
  2. 状态机校验:
当前状态处理
uploading默认路径,继续执行 HeadObject
active幂等命中,直接返回原对象,不再重复调用 HeadObject
failed返回 410 upload_failed,客户端应重新执行第一步
disabled返回 403 disabled_by_admin
记录不存在返回 404 asset_not_found
  1. 调用 COS HeadObject 获取对象真实 size / Content-Type / ETag / CRC64-ECMA。
  2. 回填字段:更新 assets 表对应记录的 size / mime_type / etag / crc64 字段,status 置为 active,updated_at 更新。
  3. 返回完整对象:url = file_key,cdn_url 由 sasset.FillCDNURL 装配。

响应参数 ​

字段说明
id素材主键,后续修改 / 删除均使用此 ID
url相对路径(即 file_key)
cdn_url公开 CDN 直链,可直接用于 image / image_url.url 字段
etagCOS 对象 ETag(MD5)
crc64COS 对象 CRC64-ECMA 校验值
statusactive 表示可用;failed 表示 HeadObject 失败,可重新调用 confirm;uploading 表示尚未执行第三步
size / mime_typeCOS 服务端权威值(覆盖第一步的占位值)

完整响应示例:

json
{
  "id": 1024,
  "user_id": 9,
  "name": "20260828153000_xxx",
  "source_type": "local",
  "file_type": "image",
  "url": "users/0_1000/9/images/20260828153000_xxx.jpg",
  "cdn_url": "https://assets.imodel.emoly.cn/users/0_1000/9/images/20260828153000_xxx.jpg",
  "size": 184320,
  "mime_type": "image/jpeg",
  "ext": "jpg",
  "etag": "abc123...",
  "crc64": "9876543210",
  "status": "active",
  "created_at": "2026-08-28T15:30:00+08:00",
  "updated_at": "2026-08-28T15:30:00+08:00"
}

错误码 ​

HTTPcode含义客户端处理建议
400invalid_json请求体 JSON 格式错误修正请求体
400missing_file_keyfile_key 未填写补充该字段
400missing_file_suffix / unsupported_file_suffix第一步参数错误重新执行第一步
401invalid_api_keyAPI Key 无效或缺失重新登录获取 sk
403file_key_prefix_mismatchfile_key 不属于当前用户命名空间禁止自行拼装 file_key,仅透传第一步响应值
403disabled_by_admin素材已被管理员禁用联系管理员
404asset_not_found找不到对应占位记录先执行第一步
404file_not_uploadedCOS 上不存在对应对象先执行第二步 PUT 上传,再调用 confirm
-(无)状态为 active 重复 confirm幂等,直接使用响应中的 cdn_url
410upload_failed状态为 failed,前次 HeadObject 失败重新执行第一步
500sts_get_failed / sign_url_failed第一步 STS / 预签名生成失败重试
500db_insert_failed第一步占位记录登记失败重试
502cos_query_failed第三步 HeadObject 失败(网络或桶配置异常)稍后重试 confirm

错误响应遵循 OpenAI 标准格式 { "error": { "type", "code", "message" } },便于 OpenAI SDK 兼容解析。

限额与安全 ​

  • 预签名有效期:presigned_url 默认 60 秒(由 configs.Tencent.Cos.Duration 配置);第三步 confirm 无时间限制(使用长凭证)
  • 文件大小限制:由网关层(nginx / ALB)与 Go 层共同兜底,建议单文件 ≤ 20MB
  • MIME 白名单:仅接受图片(jpg / png / gif / bmp / webp)、视频(mp4 / mov / avi / webm)、音频(mp3 / wav / flac / aac),其他后缀一律返回 400
  • 命名空间隔离:file_key 由 UID 自动生成,STS 临时凭证策略限定 users/{group}/{uid}/*,无法写入其他用户或任意路径
  • CORS / Referer:浏览器跨域直传 COS 需在桶上配置 CORS;若 SDK 在后端服务运行则不受 CORS 限制
  • 响应隐蔽:cdn_url 为公开 CDN 域名;响应体禁止返回 COS 上游 URL,防止前端日志或抓包获取后绕过鉴权直连 COS
  • 状态机防护:第三步严格执行 file_key 前缀与 user_id 双重所有者校验,禁止使用他人上传过的 file_key 进行 confirm