分片上传前必须校验文件可读、目录可写、os.open成功;需用filepath.abs归一化路径,head请求确认x-upload-id和已传part_numbers,再用io.seeker+io.limitreader安全读取。

分片上传前必须校验的三个状态
直接开传会丢数据。上传前得确认 file.Stat() 是否可读、os.Open() 是否成功、目标目录是否存在且可写。尤其要注意:Windows 下路径带空格或中文时,os.Stat() 可能静默失败,建议用 filepath.Abs() 先归一化路径。
断点续传依赖服务端已存分片记录,所以本地需先发一次 HEAD 请求查 X-Upload-ID 和已上传的 part_numbers 列表。别跳过这步——很多“续传失败”其实是服务端根本没返回已传分片信息。
- 用
http.DefaultClient.Timeout设为 10s,避免卡死在 HEAD 请求 - 服务端若返回
404,说明是新上传,从 part_number = 1 开始 - 若返回
200但X-Parts-Uploaded是空数组,也按新上传处理(服务端可能未持久化)
分片读取必须用 io.Seeker + io.LimitReader
不能把整个大文件 os.ReadFile() 进内存,也不能用 bufio.Scanner——它不支持偏移读。正确姿势是打开一次文件句柄,用 file.Seek(offset, io.SeekStart) 定位,再用 io.LimitReader(file, partSize) 限制本次读取长度。
常见错误:每次分片都 os.Open() 一次文件,导致 fd 耗尽;或用 file.ReadAt(buf, offset) 却忽略返回的 n, err,结果最后一片读不满 partSize 还发了完整大小的 Content-Length,服务端校验失败。
- 分片大小建议设为 5MB–10MB:太小则 HTTP 头开销占比高,太大则单片失败重传成本高
-
partSize必须是整数,别用float64计算后转int,浮点误差会导致最后一片偏移错位 - 读取后立刻用
sha256.Sum256(partData)算校验和,和服务端回传的X-Part-SHA256对,别等全部传完再校验
并发控制别碰 runtime.GOMAXPROCS,用带缓冲的 channel
设 3–5 个 goroutine 并发上传足够,再多反而因 TCP 拥塞和系统 fd 限制降低吞吐。别用 sync.WaitGroup 配无限 goroutine,也别调 runtime.GOMAXPROCS(cores*2)——上传是 IO 密集型,不是 CPU 密集型。
Colly 是一个用于 Go 语言的快速开源爬取和爬虫框架。它适用于从简单的页面提取到异步爬虫处理大量页面集合,支持请求回调和结构化解析。
正确做法是启动固定数量 worker,从一个 chan PartTask 拿任务,任务结构体里包含 PartNumber、Offset、Size 和预读好的 []byte(或 io.Reader)。worker 失败时把任务塞回 channel 重试,最多 3 次,超时直接 return error。
- channel 缓冲长度设为
len(parts) + 5,避免 worker 等待任务时阻塞主流程 - 每个 worker 自带独立
http.Client,设置Timeout: 60 * time.Second,防止某片卡住拖垮全局 - 别在 goroutine 里用闭包捕获循环变量:写
go uploadPart(p)而不是go uploadPart(part),否则所有 goroutine 传的都是最后一片
合并请求失败时,如何安全回退到断点状态
所有分片传完后发 POST /merge,服务端返回 200 才算成功。但如果合并失败(比如服务端校验总 hash 不对),你不能删掉已传分片再重来——用户等不起。
应把当前上传 ID 和已成功分片列表持久化到本地临时文件(如 $HOME/.upload_cache/<upload_id>.json</upload_id>),内容只含 upload_id、part_numbers、expires_at。下次上传同文件时,先检查该缓存是否未过期(建议设 24h 过期),再向服务端验证这些分片是否仍有效。
- 缓存文件权限设为
0600,避免敏感 upload_id 泄露 - 合并失败后不要自动重试 merge 接口——可能是服务端瞬时故障,应交由上层逻辑决定是否重试或告警
- 如果用户手动取消上传,记得调
DELETE /upload/{id}清理服务端残留分片,否则占存储
实际最难的不是并发或分片,是服务端返回的 X-Upload-ID 在客户端如何安全透传和复用。很多 bug 出现在上传中途网络抖动,客户端重连后拿了个新 ID,却还拿着旧 ID 的缓存去续传——ID 不匹配,服务端当新上传,最后合并时发现分片对不上。这个关联关系必须在每次请求响应头里严格校验。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










