Files
FileShare/docs/api/05-chunk-upload.md
T
SKYMirror 84df9996cb
CI 测试 / go vet + go test (push) Successful in 49s
26.9:版本号统一 + CI 精简 + 前端产物重建
- 全项目版本号统一:v3.x 迭代号(26.9/26.9/26.9/26.9 及裸 v2/v3)→ 26.9,
  覆盖 Go 注释 / 文档 / openapi.yaml / README×4 / 前端源码(80+ 处)
- v31_test.go 更名 custom_code_test.go;TestV2AccessorDefaults → TestKVAccessorDefaults
- docs/api/00-overview.md 更新日志合并为单条 26.9 条目(修复错位拼接)
- .goreleaser.yaml 头部注释与实际一致(Pro 2.18.1 / GITEA_TOKEN / semver tag 要求)
- CI:release-image.yml → ci.yml,仅保留 vet+test 门禁;
  镜像发布移交 GoReleaser Pro(原 build-push 的 tag 校验与 26.9 版本方案冲突,历史 9 次失败)
- 前端重建:server/web/dist 与 web-embed 同步(docs 文案嵌入更新)
2026-09-08 03:16:51 +08:00

213 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 分片上传
大文件分片上传:客户端把文件切成固定大小的分片逐个上传,服务端按索引合并并做 SHA256 校验。
支持**断点续传**(相同 `file_hash` + 大小 + 文件名的未完成会话自动续传)。
需站点开启 `enableChunk`(公共配置 `enableChunk` 返回 `true`)。
分片会话保留 24 小时。全部端点经审计中间件落库(action=upload)。
## 上传流程
```text
POST /chunk/upload/init → upload_id, total_chunks
POST /chunk/upload/{id}/{index} → 逐片上传(0 起,可并发)
GET /chunk/upload/status/{id} → 断点续传时查进度
POST /chunk/upload/complete/{id} → 合并 + SHA256 → 取件码
DELETE /chunk/upload/{id} → 取消(可选)
```
## 初始化:POST /chunk/upload/init
**请求体**JSON,亦兼容表单):
| 参数 | 类型 | 必需 | 默认 | 说明 |
|---|---|---|---|---|
| `file_name` | string | ✅ | - | 文件名(会做清理与白名单校验) |
| `file_size` | int | ✅ | - | 文件总字节数(>0;服务端按分片数校验上限) |
| `chunk_size` | int | ❌ | `5242880`(5MB) | 每片大小(字节),硬上限 32MiB(超出 400「chunk_size 过大」) |
| `file_hash` | string | ❌ | - | 整文件 SHA256(断点续传的匹配键) |
**curl 示例**
```bash
curl -s -X POST http://localhost:8466/chunk/upload/init \
-H 'Content-Type: application/json' \
-d '{"file_name":"movie.mp4","file_size":15728640,"chunk_size":5242880,"file_hash":"<sha256>"}'
```
**成功响应**200,新建会话):
```json
{
"code": 200, "msg": "ok",
"data": {
"existed": false,
"upload_id": "3f6b8c2a4d5e6f708192a3b4c5d6e7f8",
"chunk_size": 5242880,
"total_chunks": 3,
"uploaded_chunks": []
}
}
```
**断点续传响应**(200,命中未完成会话):返回既有会话,`uploaded_chunks` 为已传分片索引列表,
客户端只需补传缺失分片(注意:`existed` 字段恒为 `false`,是否续传以 `upload_id` 复用且
`uploaded_chunks` 非空为准):
```json
{
"code": 200, "msg": "ok",
"data": {
"existed": false,
"upload_id": "3f6b8c2a4d5e6f708192a3b4c5d6e7f8",
"chunk_size": 5242880,
"total_chunks": 3,
"uploaded_chunks": [0, 1]
}
}
```
**错误响应**
```json
{ "code": 400, "msg": "file_size 必须大于 0" }
```
```json
{ "code": 403, "msg": "大小超过限制,最大为10.00 MB" }
```
```json
{ "code": 403, "msg": "分片上传未启用" }
```
## 上传分片:POST /chunk/upload/{uploadID}/{chunkIndex}
主路径(与参考实现语义一致)。`chunkIndex``0` 起。
**multipart 字段**`chunk`(必需,该分片的二进制数据)。
**curl 示例**
```bash
split -b 5242880 movie.mp4 part- # 本地分片
curl -s -X POST http://localhost:8466/chunk/upload/3f6b8c2a4d5e6f708192a3b4c5d6e7f8/0 \
-F 'chunk=@./part-aa'
```
**成功响应**200):
```json
{ "code": 200, "msg": "ok", "data": { "chunk_hash": "9af1…", "chunk_index": 0 } }
```
重复上传已完成的分片(幂等跳过):
```json
{ "code": 200, "msg": "ok", "data": { "chunk_hash": "9af1…", "chunk_index": 0, "skipped": true } }
```
**错误响应**
```json
{ "code": 404, "msg": "上传会话不存在" }
```
```json
{ "code": 400, "msg": "无效的分片索引" }
```
```json
{ "code": 400, "msg": "分片大小超过声明值: 最大 5242880, 实际 5300000" }
```
```json
{ "code": 400, "msg": "缺少分片文件字段 chunk" }
```
```json
{ "code": 403, "msg": "大小超过限制,最大为10.00 MB" }
```
> 约束:单分片 ≤ `chunk_size`init 声明值)且 ≤ **32MiB 硬上限**init 时 `chunk_size>33554432` 直接 400「chunk_size 过大」);
> 总大小(init 按分片数上限、上传/合并按累计)受**动态策略上限**约束——`max_file_size>0` 时为其,
> 否则回落 `uploadSize`(26.9 需求 ④⑩,管理端改后立即生效,超限清理会话);首个分片做 magic bytes
> 防伪校验(403「文件内容校验失败:…」)。分片哈希由服务端计算;合并时与分片记录交叉校验,不一致报 400。
>
> **enableChunk 开关**:管理端关闭分片上传后,`/chunk/upload/*` 全部端点返回 403「分片上传未启用」(后端强制,前端仅隐藏入口)。
## 查询进度:GET /chunk/upload/status/{uploadID}
```bash
curl -s http://localhost:8466/chunk/upload/status/3f6b8c2a4d5e6f708192a3b4c5d6e7f8
```
**成功响应**200):
```json
{
"code": 200, "msg": "ok",
"data": {
"upload_id": "3f6b8c2a4d5e6f708192a3b4c5d6e7f8",
"file_name": "movie.mp4",
"file_size": 15728640,
"chunk_size": 5242880,
"total_chunks": 3,
"uploaded_chunks": [0, 1],
"progress": 66.66666666666667
}
}
```
## 完成合并:POST /chunk/upload/complete/{uploadID}
全部分片到齐后调用。服务端按索引有序合并 + SHA256 校验,成功后创建分享并清理分片。
**请求体**JSON,亦兼容表单):
| 参数 | 类型 | 必需 | 默认 | 说明 |
|---|---|---|---|---|
| `expire_value` | int | ❌ | `1` | 过期值 |
| `expire_style` | string | ❌ | `day` | 过期方式(同文件分享) |
```bash
curl -s -X POST http://localhost:8466/chunk/upload/complete/3f6b8c2a4d5e6f708192a3b4c5d6e7f8 \
-H 'Content-Type: application/json' \
-d '{"expire_value":1,"expire_style":"day"}'
```
**成功响应**200):
```json
{ "code": 200, "msg": "ok", "data": { "code": "R7T2K", "name": "movie.mp4" } }
```
**错误响应**
```json
{ "code": 400, "msg": "分片不完整" }
```
```json
{ "code": 400, "msg": "分片哈希校验失败,请重新上传" }
```
```json
{ "code": 403, "msg": "大小超过限制,最大为10.00 MB" }
```
## 取消上传:DELETE /chunk/upload/{uploadID}
清理分片文件与上传记录,释放容量预留。
```bash
curl -s -X DELETE http://localhost:8466/chunk/upload/3f6b8c2a4d5e6f708192a3b4c5d6e7f8
```
```json
{ "code": 200, "msg": "ok", "data": { "message": "上传已取消" } }
```
```json
{ "code": 404, "msg": "上传会话不存在" }
```