go服务启动前须创建并授权三个磁盘路径:./uploads、./tmp/chunks、./completed;http路由必须暴露/upload/chunk和/upload/merge端点,且前者需支持file_id、index、total查询参数并校验index。

Go 服务启动前必须检查的三个磁盘路径
服务跑不起来,八成卡在目录权限或路径不存在。Go 分片上传服务依赖固定路径存临时块和最终文件,./uploads、./tmp/chunks、./completed 这三处必须提前创建且进程有写权限。别信“启动时自动创建”——os.MkdirAll 在并发写入场景下可能因竞态漏建子目录,导致某次 os.OpenFile 直接 panic。
- 用
mkdir -p ./uploads ./tmp/chunks ./completed一次性建全 - 确认运行 Go 二进制的用户对这些目录有
rwx权限(chown deploy:deploy ./uploads) - 不要把
./tmp/chunks挂在 tmpfs 或内存盘上——断电即丢块,断点续传失效
HTTP 路由必须暴露 /upload/chunk 和 /upload/merge 两个端点
前端切片上传只认这两个路径,少一个就卡死。/upload/chunk 接收单块二进制数据,/upload/merge 触发合并。别套 RESTful 风格搞成 /api/v1/upload/{id}/chunk——多数前端 SDK(如 tus-js-client、七牛 SDK)硬编码了路径格式,改了就 404。
-
/upload/chunk必须支持 query 参数:file_id、index、total,且校验index -
/upload/merge的 body 只需含file_id字段,服务端据此扫描./tmp/chunks/{file_id}/下所有分片文件 - 别给这两个路由加中间件做鉴权——鉴权逻辑应放在 /upload/chunk 前置校验,否则 merge 请求可能被拦截,而分片已存盘
并发上传数设为 8 时 SSD 才不排队,设为 4 时 HDD 才不卡死
goroutine 开太多不是更快,是让内核在磁盘队列里排队。实测:同一块 NVMe SSD,并发从 4 升到 16,吞吐只增 12%,但失败率翻倍;机械盘上并发超 4,writeat 调用延迟直接从 2ms 涨到 200ms+。
在 Go 中使用 google/wire 实现编译时依赖注入——wire.NewSet、wire.Build、wire.Bind(接口→实现)、wire.Struct、wire.Value、wire.Interface
- 用带缓冲 channel 当信号量:
sem := make(chan struct{}, 8),上传前sem ,完成后 <code> - 别复用同一个
*os.File句柄给多个 goroutineWriteAt——offset 错乱会导致块内容覆盖错位 - 每个 goroutine 应独立
os.OpenFile("./tmp/chunks/xxx/chunk_001.bin", os.O_WRONLY|os.O_CREATE, 0644),写完立刻file.Close()
部署后第一件事:curl 测通 /upload/chunk 是否接受 raw body
很多部署失败源于反向代理(Nginx、Traefik)默认拒绝非 multipart 的二进制 body。curl 测不通,90% 是代理层截断了 application/octet-stream。
- 本地测:
curl -X POST "http://localhost:8080/upload/chunk?file_id=test&index=0&total=1" -H "Content-Type: application/octet-stream" --data-binary "@test.bin" - Nginx 需加配置:
client_max_body_size 0;(禁用大小限制)、proxy_buffering off;(避免缓存二进制流) - Traefik 中要在 router 上显式声明
traefik.http.routers.upload.rule=PathPrefix(`/upload`),否则中间件可能误判为 JSON 路由
真正的坑不在代码里,在 ./tmp/chunks 目录是否被定时清理脚本误删,以及 Nginx 日志里有没有 quietly dropping connection 这类提示——它意味着二进制流被静默截断,前端永远收不到 200。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










