4. MinIO 接口数据传输基础:PutObject / GetObject 接口详解、数据流与分块上传

本章是 MinIO 接口数据传输优化的基石。我们将深入剖析 PutObject 与 GetObject 两个核心接口的底层机制,对比 Streaming(数据流) 与 Multipart Upload(分块上传) 两种传输模式,为后续错误处理与中间件集成打下坚实的理论基础。

4.1 PutObject 接口:上传数据到 MinIO

PutObject 是向 MinIO 存储桶写入对象的标准接口。其核心参数包括:

参数 类型 说明
BucketName string 目标存储桶名称
ObjectName string 对象在桶中的键(Key)
Reader io.Reader 数据源,支持流式读取
ObjectSize int64 对象大小(-1 表示未知,用于流式上传)
PutObjectOptions struct 包含 Content-Type、元数据、进度回调等
关键点: 当 ObjectSize 设置为 -1 时,MinIO SDK 会自动启用 Streaming 模式,无需预先知道数据总长度。

4.1.1 标准 PutObject 示例(Go SDK)

// 标准上传:已知文件大小
file, err := os.Open("large-file.dat")
if err != nil {
    log.Fatalln(err)
}
defer file.Close()

fileInfo, _ := file.Stat()
n, err := minioClient.PutObject(ctx, "my-bucket", "my-object",
    file, fileInfo.Size(), minio.PutObjectOptions{
        ContentType: "application/octet-stream",
    })
if err != nil {
    log.Fatalln(err)
}
log.Printf("上传成功,大小:%d 字节\n", n.Size)

4.2 GetObject 接口:从 MinIO 下载数据

GetObject 用于从存储桶中读取对象。它返回一个 io.ReadCloser,支持流式读取,非常适合大文件或实时处理场景。

参数 类型 说明
BucketName string 存储桶名称
ObjectName string 对象键
GetObjectOptions struct 支持 Range 读取、版本 ID、SSE 等

4.2.1 流式读取 GetObject 示例

// 流式下载:边读边处理,无需加载到内存
object, err := minioClient.GetObject(ctx, "my-bucket", "my-object",
    minio.GetObjectOptions{})
if err != nil {
    log.Fatalln(err)
}
defer object.Close()

// 直接使用 io.Copy 写入本地文件
localFile, _ := os.Create("downloaded-file.dat")
defer localFile.Close()

written, err := io.Copy(localFile, object)
if err != nil {
    log.Fatalln(err)
}
log.Printf("下载完成,大小:%d 字节\n", written)
最佳实践: 使用 GetObject 时,务必在读取完成后调用 Close(),否则会导致连接泄漏。推荐使用 defer object.Close() 确保资源释放。

4.3 数据流(Streaming)模式详解

Streaming 模式是 MinIO 接口的核心优化点之一。它允许数据以 分块传输编码(chunked transfer encoding) 的方式发送,无需在客户端或服务端缓冲整个对象。

  • 优势: 内存占用低,支持无限大小对象,首字节延迟低。
  • 适用场景: 实时日志上传、视频流、大文件备份、管道处理。
  • 触发条件: PutObject 时 ObjectSize = -1,或使用 PutObjectStreaming 接口。
Streaming 模式 vs 非 Streaming 模式对比 非 Streaming 模式 客户端缓冲整个对象 必须预先知道对象大小 内存占用高,延迟大 Streaming 模式 数据分块实时发送 无需预先知道对象大小 内存占用低,首字节延迟小 Streaming 核心机制 使用 HTTP Transfer-Encoding: chunked 每个 chunk 独立发送,服务端边收边写

4.4 分块上传(Multipart Upload)详解

当对象大小超过 5 GiB 或网络不稳定时,推荐使用 Multipart Upload。它将大对象切分为多个 Part(每个 Part 5 MiB ~ 5 GiB),分别上传后再合并。

4.4.1 分块上传流程

  1. InitiateMultipartUpload:发起分块上传,获取 UploadID。
  2. UploadPart:按顺序上传每个 Part,记录 ETag。
  3. CompleteMultipartUpload:提交所有 Part,合并为完整对象。
  4. AbortMultipartUpload:取消未完成的上传,释放资源。
步骤 API 名称 关键参数 说明
1 NewMultipartUpload Bucket, Object 返回 UploadID
2 PutObjectPart UploadID, PartNumber, Reader 上传单个分片,返回 ETag
3 CompleteMultipartUpload UploadID, Parts[] 合并分片,生成最终对象
4 AbortMultipartUpload UploadID 取消上传,清理临时分片

4.4.2 分块上传示例(Go SDK)

// 分块上传核心逻辑
uploadID, err := minioClient.NewMultipartUpload(ctx, "my-bucket", "large-object",
    minio.PutObjectOptions{})
if err != nil {
    log.Fatalln(err)
}

var parts []minio.CompletePart
for i := 1; i <= totalParts; i++ {
    // 读取第 i 个分片
    partData := readPart(i)
    uploadInfo, err := minioClient.PutObjectPart(ctx, "my-bucket", "large-object",
        uploadID, i, partData, partSize, minio.PutObjectPartOptions{})
    if err != nil {
        // 出错时中止上传
        minioClient.AbortMultipartUpload(ctx, "my-bucket", "large-object", uploadID)
        log.Fatalln(err)
    }
    parts = append(parts, minio.CompletePart{
        PartNumber: i,
        ETag:       uploadInfo.ETag,
    })
}

// 完成上传
_, err = minioClient.CompleteMultipartUpload(ctx, "my-bucket", "large-object",
    uploadID, parts, minio.PutObjectOptions{})
if err != nil {
    log.Fatalln(err)
}
注意: 分块上传的 Part 必须按顺序上传,但可以并发执行。并发上传时,需要确保 PartNumber 正确对应。推荐使用 errgroup 或 worker pool 控制并发度。
Multipart Upload 完整流程 1. Initiate 2. Upload Parts(并发) Part 1 Part 2 Part 3 Part N 3. Complete 4. 对象可用

4.5 Streaming 与 Multipart Upload 对比

特性 Streaming Multipart Upload
适用对象大小 任意大小(推荐 < 5 GiB) > 5 MiB(推荐 > 5 GiB)
是否需要预知大小 否 否(但需分片策略)
内存占用 低(流式处理) 中(需缓冲分片)
并发上传 不支持 支持(多 Part 并发)
断点续传 不支持 支持(可重试失败 Part)
首字节延迟 低 高(需等待所有 Part 完成)
典型场景 实时日志、视频流 大文件备份、数据迁移
选型建议: 对于小于 5 GiB 且网络稳定的场景,优先使用 Streaming 模式;对于大文件、弱网络或需要断点续传的场景,使用 Multipart Upload。实际生产环境中,两者可以结合使用:先尝试 Streaming,失败后自动降级为 Multipart Upload。

4.6 本章小结

  • PutObject / GetObject 是 MinIO 数据传输的基础接口,支持流式读写。
  • Streaming 模式 通过 chunked transfer encoding 实现低内存、低延迟传输。
  • Multipart Upload 通过分片并发上传,解决大文件传输的可靠性和效率问题。
  • 理解这两种模式的区别与适用场景,是后续实现错误处理、重试策略和中间件集成的前提。