初始化分片上传
1. 接口定位
- 接口名称: 初始化分片上传
- 所属域: object
- 业务目标: 发起大文件的分片上传会话;若服务端已存在相同 hash 的文件,则直接返回访问 URL(秒传),否则返回分片上传所需的签名信息
2. 请求定义
- Method:
POST - Path:
/object/initiate_multipart_upload - Content-Type: 推荐
application/json - operationID: 必填,请通过 Header
operationID传入 - 鉴权: 必填,需要通过 Header
token传入有效令牌 - 幂等性: 非幂等(会话状态与签名 URL 有时效性)
3. 请求参数
Header 参数
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
| operationID | 是 | string | 链路追踪 ID |
| token | 是 | string | 登录令牌 |
Body 参数
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
| hash | 是 | string | 文件内容的 MD5 哈希(hex 编码),用于秒传判断和完整性校验 |
| size | 是 | int64 | 文件总大小(字节) |
| maxParts | 否 | int32 | 期望的最大分片数,服务端会据此计算建议分片大小 |
| name | 是 | string | 目标对象存储路径(含文件名),如 user/avatar/xxx.jpg |
| contentType | 否 | string | 文件 MIME 类型,如 image/jpeg |
| cause | 否 | string | 上传来源标记,用于文件分组管理 |
| urlPrefix | 否 | string | 返回 URL 的前缀(scheme+host),不传则使用服务端默认配置 |
4. 响应结构
通用响应包裹
| 字段 | 类型 | 说明 |
|---|---|---|
| errCode | int | 错误码,0 表示成功 |
| errMsg | string | 错误简述 |
| errDlt | string | 错误详情 |
| data | any | 业务数据 |
两种响应路径
服务端会对 hash 做已存在判断,返回结构因此有两种情况:
路径一:秒传(文件已存在)
data.upload 为 null,data.url 不为空,调用方可直接使用该 URL,无需继续上传。
| 字段 | 类型 | 说明 |
|---|---|---|
| url | string | 文件访问 URL |
| upload | null | 秒传时不返回上传信息 |
路径二:需要分片上传
data.upload 不为 null,调用方需按签名信息完成各分片上传后调用 complete_multipart_upload 提交。
| 字段 | 类型 | 说明 |
|---|---|---|
| url | string | 上传完成后可使用的预期 URL(完成前无效) |
| upload | object | 分片上传会话信息 |
upload 字段结构
| 字段 | 类型 | 说明 |
|---|---|---|
| uploadID | string | 分片上传会话 ID,complete_multipart_upload 时需要 |
| partSize | int64 | 每个分片的大小(字节),客户端按此分割文件 |
| sign | object | 分片上传签名信息(部分存储后端可能为 null) |
| expireTime | int64 | 签名过期时间(毫秒时间戳),超时后需重新发起 |
sign 字段结构
| 字段 | 类型 | 说明 |
|---|---|---|
| url | string | 基础上传 URL |
| query | array[object] | 公共 query 参数,每个元素含 key(string)和 values(array[string]) |
| header | array[object] | 公共请求头参数 |
| parts | array[object] | 各分片的独立签名,见下表 |
parts 元素(SignPart)
| 字段 | 类型 | 说明 |
|---|---|---|
| partNumber | int32 | 分片序号(从 1 开始) |
| url | string | 该分片的上传 URL |
| query | array[object] | 该分片的 query 参数 |
| header | array[object] | 该分片的请求头参数 |
5. 业务规则
- 调用方持有合法 token 即可调用,无角色限制。
- 服务端对请求的
name做命名规则校验,非法文件名会返回参数错误。 - 上传签名有有效期(
expireTime),过期后需重新调用本接口获取新签名。 - 分片上传流程:
initiate_multipart_upload→ 按parts中的签名逐片 PUT →complete_multipart_upload。 - 若请求时文件 hash 已存在,服务端直接入库并返回 URL,跳过上传流程(秒传)。
6. 错误码与失败场景
| 错误码 | 场景 | 典型报错 |
|---|---|---|
| 1001 | 参数不合法(hash 为空、文件名非法等) | ArgsError |
| 500 | 服务内部错误(对象存储调用失败等) | ServerInternalError |
7. 示例
fetch 请求示例
javascript
fetch("http://localhost:10002/object/initiate_multipart_upload", {
method: "POST",
headers: {
operationID: "c57f1e82-0d3b-4ade-a5f5-e9f3b2d94f03",
token: "<your-token>",
"Content-Type": "application/json",
},
body: JSON.stringify({
hash: "d41d8cd98f00b204e9800998ecf8427e",
size: 52428800,
maxParts: 10,
name: "user/file/20260620/example.mp4",
contentType: "video/mp4",
cause: "chat_attachment",
}),
})
.then((res) => res.json())
.then((data) => console.log(data));请求示例(JSON)
json
{
"hash": "d41d8cd98f00b204e9800998ecf8427e",
"size": 52428800,
"maxParts": 10,
"name": "user/file/20260620/example.mp4",
"contentType": "video/mp4",
"cause": "chat_attachment"
}成功响应示例(需上传)
json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"url": "https://minio.example.com/openim/user/file/20260620/example.mp4",
"upload": {
"uploadID": "3a7b5c-upload-session-id",
"partSize": 5242880,
"expireTime": 1750501200000,
"sign": {
"url": "https://minio.example.com/openim",
"query": [],
"header": [],
"parts": [
{
"partNumber": 1,
"url": "https://minio.example.com/openim/part1",
"query": [{ "key": "partNumber", "values": ["1"] }],
"header": []
}
]
}
}
}
}成功响应示例(秒传)
json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"url": "https://minio.example.com/openim/user/file/20260620/example.mp4",
"upload": null
}
}8. 时序流程
完整分片上传流程:
- 调用
initiate_multipart_upload,获取uploadID和各分片签名。 - 客户端按
partSize分割文件,对每个分片调用parts[i].url(PUT 请求,附带对应 query/header)。 - 所有分片上传完成后,调用
complete_multipart_upload提交,获取最终 URL。
秒传场景:
- 调用
initiate_multipart_upload,若 hash 命中服务端缓存,直接返回url,upload为null。 - 调用方直接使用返回的 URL,不需要上传。
9. 变更记录
- 2026-06-20: 首版补充文档发布。