- 数据库默认文件 filecodebox.db → fileshare.db(config.go 默认值与全部文档/编排同步)
- Go module filecodebox → fileshare(全部 import 同步,build/vet/test 全绿)
- 应用版本 APP_VERSION 2.5.6 → 26.9(health 接口已验证返回 26.9)
- deploy 编排统一:compose 项目名、Postgres 默认凭据、minio 桶名、env 注释
- JWT issuer、存储临时目录前缀、web 包名同步 fileshare
- CI:镜像 tag 以 APP_VERSION 为唯一版本源,main/tag 推送即发布
${VER} + latest;tag 触发时校验 tag 名与 APP_VERSION 一致,防错版
- 本地开发库文件已改名 fileshare.db(含 -shm/-wal 清理)
5.9 KiB
5.9 KiB
预签名直传
服务端预生成上传地址,客户端直接向存储引擎(或服务端代理)上传文件,最后确认建分享。 两种模式:
| 模式 | 引擎 | 上传方式 |
|---|---|---|
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)。
上传流程
direct 模式:
POST /presign/upload/init → upload_url(S3 预签名 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 示例:
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"}'
S3(direct)成功响应(200):
{
"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/WebDAV(proxy)成功响应(200):
{
"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…"
}
}
错误响应:
{ "code": 403, "msg": "大小超过限制,最大为10.00 MB" }
大小上限为动态策略(v2 需求 ④⑩):管理端改
max_file_size(0=回落uploadSize)后 立即按新上限校验 init 声明的file_size。
{ "code": 403, "msg": "不允许上传该类型文件" }
{ "code": 507, "msg": "存储空间已达到管理员设置的容量上限" }
直传确认:POST /presign/upload/confirm/{uploadID}
direct 模式专用:客户端向 S3 PUT 完成后调用。服务端会核对实际对象(多引擎一致):
- 大小核对:实际大小与声明差 >1KB → 400「文件大小与声明不符」;超过策略上限(
max_file_size)→ 删除对象、释放容量预留并 403; - 内容校验:取对象前 64 字节做 magic bytes 白名单校验(失败删除对象并报错);
- 全部通过后创建分享记录。
# 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):
{ "code": 200, "msg": "ok", "data": { "code": "B4N8Q", "name": "backup.zip" } }
错误响应:
{ "code": 404, "msg": "文件未上传或上传失败" }
{ "code": 400, "msg": "文件大小与声明不符" }
{ "code": 403, "msg": "文件大小超过限制" }
{ "code": 400, "msg": "此会话不支持direct模式" }
代理上传:PUT /presign/upload/proxy/{uploadID}
proxy 模式专用:multipart 上传到服务端,服务端流式转存到存储引擎后立即创建分享记录。
multipart 字段:file(必需)。
curl 示例:
curl -s -X PUT http://localhost:8466/presign/upload/proxy/6a1e… -F 'file=@./backup.zip'
成功响应(200):
{ "code": 200, "msg": "ok", "data": { "code": "B4N8Q", "name": "backup.zip" } }
错误响应:
{ "code": 400, "msg": "缺少上传文件 file 字段" }
{ "code": 400, "msg": "文件大小与声明不符" }
{ "code": 403, "msg": "大小超过限制,最大为10.00 MB" }
文件实际大小须与 init 声明的
file_size一致(±1KB 容差);成功后会话即删除,不可重复使用。
查询会话:GET /presign/upload/status/{uploadID}
curl -s http://localhost:8466/presign/upload/status/6a1e…
成功响应(200):
{
"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 的对象。
curl -s -X DELETE http://localhost:8466/presign/upload/6a1e…
{ "code": 200, "msg": "ok", "data": { "message": "上传会话已取消" } }
{ "code": 404, "msg": "上传会话不存在" }
{ "code": 404, "msg": "上传会话已过期" }