直接用PutObject不适合大文件上传,因其无法断点续传、无进度跟踪且中断需全量重传;MinIO通过分片上传(Multipart Upload)支持断点续传,需先调InitiateMultipartUpload获取uploadID并持久化,再按partNumber逐个上传分片并保存ETag,最后用ListObjectParts恢复状态、补传缺失分片,并按序CompleteMultipartUpload完成合并。

为什么直接用 PutObject 不适合大文件上传
因为 PutObject 要求整个文件内容一次性加载进内存或通过 io.Reader 流式读取,但无法记录上传进度、无法暂停恢复、服务端中断后必须重传全部。MinIO 原生支持 S3 兼容的分片上传(Multipart Upload),这才是断点续传的基础。
如何发起分片上传并保存 uploadID
调用 InitiateMultipartUpload 获取唯一 uploadID,这是后续所有分片和完成操作的凭证。必须自己持久化这个 ID(比如存数据库或本地文件),否则断点时无法续传。
-
uploadID有效期默认 7 天,超时后所有已传分片会被 MinIO 自动清理 - 同一个对象 key 可同时存在多个未完成的
uploadID,靠uploadID区分,不是靠 key - 示例关键调用:
res, err := minioClient.InitiateMultipartUpload(ctx, bucketName, objectName, nil)
,res.UploadID就是你要存下来的值
如何上传分片并记录每个 partNumber 和 etag
每个分片需指定 partNumber(1–10000 的整数,不能跳号、不能重复),上传成功后 MinIO 返回 ETag(即该分片的 MD5 base64 值)。这两项必须和 uploadID 一起存下来,缺一不可。
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
- 分片大小建议 ≥ 5 MiB(S3 规范要求),太小会导致请求过多、性能下降;单个对象最多 10000 个分片
- 上传时用
PutObjectPart,传入uploadID、partNumber、分片数据流和长度 - 务必校验返回的
ETag字段,它会在后续CompleteMultipartUpload中作为完整性依据 - 不要依赖客户端计算的 MD5——MinIO 返回的
ETag才是权威值
如何恢复上传和完成合并
断点续传 = 查询已传分片 + 补传缺失分片 + 完成合并。MinIO 提供 ListMultipartUploads 和 ListObjectParts,但注意:前者查的是“未完成的 upload”,后者查的是“某个 uploadID 下已传的 parts”。
- 恢复前先调
ListObjectParts,传入原始uploadID,拿到已成功上传的partNumber列表和对应ETag - 只对缺失的
partNumber发起新上传,其余跳过 - 完成时构造
CompleteMultipartUpload所需的parts列表:必须按partNumber升序排列,且每个元素包含PartNumber和ETag(必须用之前保存的值,不能用新上传返回的——除非你重传了) - 一旦
CompleteMultipartUpload成功,该uploadID失效,不能再追加分片
最易忽略的一点:分片上传不是原子操作,uploadID 和每个分片的 ETag 必须落盘(哪怕只是临时文件),网络抖动或进程崩溃后,仅靠内存状态无法恢复。

















