- 改动:init/check 接受可选 targetDir(相对 CloudDir,SanitizeDir 校验),merge 物理落盘 CloudDir/<targetDir>/ - 秒传跨目录 copy-on-hit:库把旧物理文件复制进目标目录,OnInstantHit 携带新路径;源缺失回退正常上传 - 断点续传按目录隔离:同 MD5 在途任务目录不同则另起新任务 - TaskInfo 新增 TargetDir(宿主须持久化);Repository 12 方法接口零变更,向后兼容 v1.0.x - 新增 dir.go(SanitizeDir/路径拼装反解/copyFile)与 service_test.go(10 个用例:双模式秒传/续传隔离/merge 回归) - 原因:上传位置原本固定在 CloudDir 根,宿主无法实现网盘式选目录上传
65 lines
3.7 KiB
Markdown
65 lines
3.7 KiB
Markdown
# fileupload
|
||
|
||
通用大文件分片上传 Go/Gin 服务端核心(独立库,原 zogo/fileupload 子包)。
|
||
六接口(init/chunk/merge/check/task/abort)+ 分片幂等 + 断点续传 + `.part` 原子改名 + 合并整文件 MD5 校验 + 秒传 + 目标目录(targetDir)。
|
||
不依赖宿主的响应封装、ORM 或业务表——存储走 `Repository` 接口注入,业务衔接走 `Options` 回调。
|
||
|
||
## 用法
|
||
|
||
```go
|
||
import "git.zeroonesoft.cn/golib/fileupload"
|
||
|
||
opts := fileupload.Options{
|
||
ChunkRoot: "./data/upload-chunks", // 分片临时目录(建议在静态根之外)
|
||
CloudDir: "./data/uploads/cloud", // 合并产物目录(targetDir 的根)
|
||
WebPathPrefix: "cloud", // storagePath 的 Web 前缀(须与 CloudDir 相对静态根的子目录一致)
|
||
URLPrefix: "/uploads", // fileUrl = URLPrefix + "/" + storagePath
|
||
MaxTotalSizeMB: 2048, // 0=不限
|
||
OnMerged: func(t fileupload.TaskInfo) error {
|
||
// 合并成功:宿主写自己的业务表(如云盘记录行);失败则 merge 整体失败
|
||
return nil
|
||
},
|
||
OnInstantHit: func(t fileupload.TaskInfo) error {
|
||
// 秒传命中:宿主确保业务侧可见行(可空回调);跨目录命中时携带新 StoragePath/TargetDir
|
||
return nil
|
||
},
|
||
Envelope: func(c *gin.Context, resp any, err error) {
|
||
// 宿主自己的响应封装,如 httpx.HandleResult(c, resp, err)
|
||
},
|
||
}
|
||
_ = fileupload.Mount(api.Group("/upload"), opts, myRepo,
|
||
fileupload.WithIdentity(func(c *gin.Context) (string, int64) {
|
||
return c.GetString("UserName"), c.GetInt64("TenantId")
|
||
}))
|
||
```
|
||
|
||
`Repository`(12 个方法)由宿主按自己的表结构实现;软删/硬删自定,但删除后查询必须不可见。
|
||
鉴权由宿主路由组的 JWT 中间件统一负责,本库不感知。
|
||
|
||
## 目标目录(targetDir)
|
||
|
||
上传位置不再固定:init 请求可带 `targetDir`(相对 `CloudDir`,`/` 分隔,**空=根目录**),
|
||
合并产物物理落盘 `CloudDir/<targetDir>/<产物名>`,storagePath = `WebPathPrefix + "/" + targetDir + "/" + 产物名`。
|
||
`/check` 亦接受可选 query `targetDir`。宿主可用 `fileupload.SanitizeDir` 复用同款目录校验
|
||
(拒绝 `..`/`.`/空段/绝对路径/Windows 非法字符,限长 500、限深 16)。
|
||
|
||
三档宿主形态(服务端无模式概念,字段缺省即固定路径模式,v1.0.x 行为不变):
|
||
|
||
| 形态 | 客户端行为 | 服务端表现 |
|
||
|---|---|---|
|
||
| 固定路径(默认) | 不传 targetDir | 与 v1.0.x 完全一致,落 CloudDir 根 |
|
||
| 固定子目录 | 每次上传带同一 targetDir | 固定落该子目录 |
|
||
| 网盘式自选 | 用户选目录后随 init 传入 | 落所选子目录,`MkdirAll` 自动创建 |
|
||
|
||
语义要点:
|
||
|
||
- **秒传 copy-on-hit**:秒传按全局 MD5 命中。同目录(含根目录)命中直接复用旧文件;跨目录命中由库把旧物理文件复制进目标目录,`OnInstantHit` 携带新 `StoragePath`/`TargetDir`;旧物理文件缺失或复制失败自动回退为正常分片上传。
|
||
- **断点续传按目录隔离**:同 MD5 在途任务目标目录不同时不复用,另起新任务。
|
||
- **宿主须持久化 `TaskInfo.TargetDir`**(建议 `upload_task` 加 `target_dir varchar(500)`):不持久化时目录上传的断点续传会退化为每次新建任务,其余功能不受影响。
|
||
|
||
## 版本
|
||
|
||
- v1.1.0 新增 targetDir:init/check 支持目标目录,跨目录秒传 copy-on-hit,续传按目录隔离;Repository 接口零变更
|
||
- v1.0.0 首个独立 tag:自 zogo/fileupload v0.3.2 抽出
|
||
- v0.1.0 初版:自 FileUpload 项目 restful/upload 模块抽出
|