Files
FileShare/docs/api/06-presign.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

211 lines
5.9 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.
# 预签名直传
服务端预生成上传地址,客户端直接向存储引擎(或服务端代理)上传文件,最后确认建分享。
两种模式:
| 模式 | 引擎 | 上传方式 |
|---|---|---|
| `direct` | S3(含 MinIO/R2 等 S3 兼容存储) | 客户端 `PUT` 到预签名 URL,直连对象存储 |
| `proxy` | 本地 / WebDAV | 客户端 `PUT` multipart 到服务端代理接口 |
> 本地 / WebDAV 引擎不支持预签名直链,init 返回正常 `proxy` 模式(仅当引擎预签名调用本身异常时才报错)。
> 会话有效期 **900 秒**(15 分钟)。proxy 模式响应另含 `legacy_proxy_upload_url`
> (`/api` 前缀的兼容别名,已废弃,与 `upload_url` 等价)。
> 全部端点经审计中间件落库(action=upload)。
## 上传流程
```text
direct 模式:
POST /presign/upload/init → upload_urlS3 预签名 PUT
PUT <upload_url> → 客户端直传 S3(无认证头)
POST /presign/upload/confirm/{id} → 确认 → 取件码
proxy 模式:
POST /presign/upload/init → upload_url = /presign/upload/proxy/{id}
PUT /presign/upload/proxy/{id} → multipart 上传,服务端转存并直接建分享
```
## 初始化:POST /presign/upload/init
**请求体**JSON,亦兼容表单):
| 参数 | 类型 | 必需 | 默认 | 说明 |
|---|---|---|---|---|
| `file_name` | string | ✅ | - | 文件名(清理 + 白名单校验) |
| `file_size` | int | ✅ | - | 文件字节数(≤ 生效上限:`max_file_size>0` 时为其,否则 `uploadSize` |
| `expire_value` | int | ❌ | `1` | 过期值(`count` 型受 `max_save_count` 约束) |
| `expire_style` | string | ❌ | `day` | 过期方式(须在 `expireStyle` 白名单内) |
**curl 示例**
```bash
curl -s -X POST http://localhost:8466/presign/upload/init \
-H 'Content-Type: application/json' \
-d '{"file_name":"backup.zip","file_size":20971520,"expire_value":7,"expire_style":"day"}'
```
**S3direct)成功响应**200):
```json
{
"code": 200, "msg": "ok",
"data": {
"upload_id": "6a1e…",
"upload_url": "https://minio:9000/fileshare/share/data/2025/06/01/6a1e…/backup.zip?X-Amz-…",
"mode": "direct",
"expires_in": 900,
"file_path": "share/data/2025/06/01/6a1e…"
}
}
```
**local/WebDAVproxy)成功响应**200):
```json
{
"code": 200, "msg": "ok",
"data": {
"upload_id": "6a1e…",
"upload_url": "/presign/upload/proxy/6a1e…",
"proxy_upload_url": "/presign/upload/proxy/6a1e…",
"mode": "proxy",
"expires_in": 900,
"file_path": "share/data/2025/06/01/6a1e…"
}
}
```
**错误响应**
```json
{ "code": 403, "msg": "大小超过限制,最大为10.00 MB" }
```
> 大小上限为动态策略(26.9 需求 ④⑩):管理端改 `max_file_size`0=回落 `uploadSize`)后
> 立即按新上限校验 init 声明的 `file_size`。
```json
{ "code": 403, "msg": "不允许上传该类型文件" }
```
```json
{ "code": 507, "msg": "存储空间已达到管理员设置的容量上限" }
```
## 直传确认:POST /presign/upload/confirm/{uploadID}
`direct` 模式专用:客户端向 S3 `PUT` 完成后调用。服务端会核对实际对象(多引擎一致):
- **大小核对**:实际大小与声明差 >1KB → 400「文件大小与声明不符」;超过策略上限(`max_file_size`)→ **删除对象、释放容量预留**并 403;
- **内容校验**:取对象前 64 字节做 magic bytes 白名单校验(失败删除对象并报错);
- 全部通过后创建分享记录。
```bash
# 1) 直传 S3(注意:不要带 Authorization 头,预签名 URL 自带鉴权)
curl -X PUT "<data.upload_url>" --upload-file ./backup.zip
# 2) 确认
curl -s -X POST http://localhost:8466/presign/upload/confirm/6a1e…
```
**成功响应**200):
```json
{ "code": 200, "msg": "ok", "data": { "code": "B4N8Q", "name": "backup.zip" } }
```
**错误响应**
```json
{ "code": 404, "msg": "文件未上传或上传失败" }
```
```json
{ "code": 400, "msg": "文件大小与声明不符" }
```
```json
{ "code": 403, "msg": "文件大小超过限制" }
```
```json
{ "code": 400, "msg": "此会话不支持direct模式" }
```
## 代理上传:PUT /presign/upload/proxy/{uploadID}
`proxy` 模式专用:multipart 上传到服务端,服务端流式转存到存储引擎后立即创建分享记录。
**multipart 字段**`file`(必需)。
**curl 示例**
```bash
curl -s -X PUT http://localhost:8466/presign/upload/proxy/6a1e… -F 'file=@./backup.zip'
```
**成功响应**200):
```json
{ "code": 200, "msg": "ok", "data": { "code": "B4N8Q", "name": "backup.zip" } }
```
**错误响应**
```json
{ "code": 400, "msg": "缺少上传文件 file 字段" }
```
```json
{ "code": 400, "msg": "文件大小与声明不符" }
```
```json
{ "code": 403, "msg": "大小超过限制,最大为10.00 MB" }
```
> 文件实际大小须与 init 声明的 `file_size` 一致(±1KB 容差);成功后会话即删除,不可重复使用。
## 查询会话:GET /presign/upload/status/{uploadID}
```bash
curl -s http://localhost:8466/presign/upload/status/6a1e…
```
**成功响应**200):
```json
{
"code": 200, "msg": "ok",
"data": {
"upload_id": "6a1e…",
"file_name": "backup.zip",
"file_size": 20971520,
"mode": "proxy",
"created_at": "2025-06-01T12:00:00+08:00",
"expires_at": "2025-06-01T12:15:00+08:00",
"is_expired": false
}
}
```
## 取消会话:DELETE /presign/upload/{uploadID}
删除会话并释放容量预留;`direct` 模式会尽力清理已直传到 S3 的对象。
```bash
curl -s -X DELETE http://localhost:8466/presign/upload/6a1e…
```
```json
{ "code": 200, "msg": "ok", "data": { "message": "上传会话已取消" } }
```
```json
{ "code": 404, "msg": "上传会话不存在" }
```
```json
{ "code": 404, "msg": "上传会话已过期" }
```