如何使用 MinIO 的 S3 ZIP 扩展直接列出并下载 ZIP 对象内的文件?
2026/9/9 19:20:49 网站建设 项目流程

如何使用 MinIO 的 S3 ZIP 扩展直接列出并下载 ZIP 对象内的文件?

【免费下载链接】minioMinIO is a high-performance, S3 compatible object store, open sourced under GNU AGPLv3 license.项目地址: https://gitcode.com/GitHub_Trending/mi/minio

当一个 ZIP 归档已经作为普通 S3 对象上传到 MinIO 的某个 bucket 时,MinIO 的 S3 ZIP 扩展允许你用常规 S3 API 直接列出归档内的文件、并下载其中指定的单个文件,而不必先下载整个 ZIP 再解压。启用方式只有一个:在请求中附加x-minio-extracttrue的 header,并在请求路径上把归档内路径拼接到归档对象的 key 之后。仓库自带 S3 ZIP 扩展说明 和三个语言的完整示例(boto3、minio-go、AWS JS SDK v2),本文以这些示例为操作路径,说明"列出"和"下载"两个动作怎么做、以及如何判断结果。

启用方式与请求路径规则

完成本场景需要遵循的协议约定(来自 docs/extensions/s3zip/README.md):

  1. 在 S3 请求上设置 header:x-minio-extract值为true
  2. 访问归档内部内容时,把归档内路径直接追加到归档对象 key 之后。文档给出的例子:要下载存储在 bucketcompany-datafinancial.zip内的2021/taxes.csv,发起 GET 请求使用的路径为company-data/financial.zip/2021/taxes.csv
  3. 该扩展仅适用于对 ZIP 内文件的以下操作:HeadObjectGetObjectListObjectsV2
  4. 边界限制:要更新或删除 ZIP 内某个文件的内容,必须整体替换 ZIP 文件。

准备条件

  • 一个可访问的 MinIO 服务。三个示例中使用的 endpoint 分别为http://localhost:9000(boto3)、http://127.0.0.1:9000(JS)、minio-server-address:9000(Go,占位符),按实际部署地址替换。
  • 可用的访问凭证。示例中的YOUR-ACCESSKEYID/YOUR-SECRETACCESSKEYaccess-key/secret-key均为占位符,需替换为你自己的 AccessKey 和 SecretKey。
  • 客户端 SDK 需要能够设置自定义 HTTP header。仓库示例分别依赖 boto3(AWS SDK for Python)、github.com/minio/minio-go/v7aws-sdk(JS,见 package.json 中声明的aws-sdk ^2.924.0)。

示例代码位于 examples 目录,下文路径均相对仓库根目录。

列出 ZIP 内的文件(boto3 主路径)

docs/extensions/s3zip/examples/boto3/main.py 同时覆盖了列出与下载,是最完整的参考。完整示例如下:

#!/usr/bin/env/python import boto3 from botocore.client import Config s3 = boto3.client('s3', endpoint_url='http://localhost:9000', aws_access_key_id='YOUR-ACCESSKEYID', aws_secret_access_key='YOUR-SECRETACCESSKEY', config=Config(signature_version='s3v4'), region_name='us-east-1') def _add_header(request, **kwargs): request.headers.add_header('x-minio-extract', 'true') event_system = s3.meta.events event_system.register_first('before-sign.s3.*', _add_header) # List zip contents response = s3.list_objects_v2(Bucket="your-bucket", Prefix="path/to/file.zip/") print(response) # Download data.csv stored in the zip file s3.download_file(Bucket='your-bucket', Key='path/to/file.zip/data.csv', Filename='/tmp/data.csv')

示例中需要替换的值:

  • endpoint_url:MinIO 服务地址,示例为http://localhost:9000
  • YOUR-ACCESSKEYID/YOUR-SECRETACCESSKEY:你的访问凭证;
  • your-bucket:存放 ZIP 归档的 bucket 名;
  • path/to/file.zip/:归档对象的 key 后加/,作为Prefix
  • path/to/file.zip/data.csv:归档 key 后接归档内目标文件的相对路径。

两点需要注意:

  • 文档明确要求使用ListObjectsV2来列出 ZIP 内容,示例中的list_objects_v2与该要求一致,不要换成 ListObjectsV1。
  • header 是通过event_system.register_first('before-sign.s3.*', _add_header)注册到事件系统上的,对该 client 之后的 S3 请求(包括随后的download_file)统一生效,因此下载调用本身不需要再单独设置 header。

下载 ZIP 内的单个文件

下载就是普通的GetObject,只是对象 key 写成"归档 key + 归档内路径"。上述示例最后一行s3.download_file(Bucket='your-bucket', Key='path/to/file.zip/data.csv', Filename='/tmp/data.csv')会把 ZIP 内的data.csv直接写到/tmp/data.csv。如果你只需要读取内容而不落盘,Go 示例展示的是把对象内容输出到 stdout 的写法(见下一节)。

替代 SDK:minio-go 与 AWS JS SDK v2(可选分支)

如果你使用 Go 或 Node.js 客户端,按 minio-go 示例 和 AWS JS 示例 设置 header 即可。

minio-go(注意minio-server-address是占位符,access-key/secret-key需替换为真实凭证):

package main import ( "context" "io" "log" "os" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" ) func main() { s3Client, err := minio.New("minio-server-address:9000", &minio.Options{ Creds: credentials.NewStaticV4("access-key", "secret-key", ""), }) if err != nil { log.Fatalln(err) } var opts minio.GetObjectOptions // Add extract header to request: opts.Set("x-minio-extract", "true") // Download API.md from the archive rd, err := s3Client.GetObject(context.Background(), "your-bucket", "path/to/file.zip/data.csv", opts) if err != nil { log.Fatalln(err) } _, err = io.Copy(os.Stdout, rd) if err != nil { log.Fatalln(err) } }

该示例下载path/to/file.zip内的data.csv,并把文件内容直接输出到 stdout;出错时通过log.Fatalln终止。

AWS JS SDK v2(your-bucketpath/to/file.zip/path/to/file.zip/data.csv均为需要替换的占位值;header 通过on('build')钩子在签名前注入):

var AWS = require('aws-sdk'); var s3 = new AWS.S3({ accessKeyId: 'YOUR-ACCESSKEYID' , secretAccessKey: 'YOUR-SECRETACCESSKEY' , endpoint: 'http://127.0.0.1:9000' , s3ForcePathStyle: true, signatureVersion: 'v4' }); // List all contents stored in the zip archive s3.listObjectsV2({Bucket : 'your-bucket', Prefix: 'path/to/file.zip/'}). on('build', function(req) { req.httpRequest.headers['X-Minio-Extract'] = 'true'; }). send(function(err, data) { if (err) { console.log("Error", err); } else { console.log("Success", data); } }); // Download a file in the archive and store it in /tmp/data.csv var file = require('fs').createWriteStream('/tmp/data.csv'); s3.getObject({Bucket: 'your-bucket', Key: 'path/to/file.zip/data.csv'}). on('build', function(req) { req.httpRequest.headers['X-Minio-Extract'] = 'true'; }). on('httpData', function(chunk) { file.write(chunk); }). on('httpDone', function() { file.end(); }). send();

如何判断操作成功

示例代码本身给出的判断方式:

  • 列出:boto3 示例print(response)打印 ListObjectsV2 的响应;JS 示例的回调在失败时打印Error和错误对象,成功时打印Success和数据。如果列出的条目里出现了你预期在 ZIP 内的文件路径,说明x-minio-extractheader 与Prefix均配置正确。
  • 下载:JS 示例把内容写入/tmp/data.csvhttpDone时结束写流);boto3 示例落盘到/tmp/data.csv;Go 示例把内容输出到 stdout。检查目标文件内容与 ZIP 内原文件一致即完成。

文档没有给出固定的示例输出,上面各打印内容以你实际环境中返回的响应为准。

限制与边界

来自 docs/extensions/s3zip/README.md 的 "Requirements and limits",直接使用 ZIP 内文件前应先确认归档满足这些条件:

  • ListObjectsV2只能列出对象最近一个版本的 ZIP 归档内容,仅适用于版本化 bucket。
  • 列出 ZIP 内容必须使用ListObjectsV2
  • 不支持对 ZIP 内单个文件发起GetObject/HeadObjectRange 请求
  • ZIP 内文件名保持原样不做修改,但某些名字可能构成非法路径;命名安全性需参照 S3 对象 key 命名规范自行检查。
  • 如果 ZIP 的中心目录(directory)不在文件的最后 100MB 范围内,该文件将不被解析。
  • 单个 ZIP 内允许的最大规模为 100M;同时文档建议单个 ZIP 内文件数控制在 100,000 以内,以获得性能与内存的合理折中。
  • 除文件大小外的属性(修改时间、header、标签等)都只绑定在 ZIP 文件整体上,只能对整个 ZIP 设置;同理,bucket 复制(replication)复制的是整个 ZIP 文件而不是其中单个文件。
  • 响应的Content-Type由文件扩展名决定(按 Gomime.TypeByExtension的规则解析)。

如果归档超出上述限制(例如中心目录不在最后 100MB 内),该 ZIP 不会被解析,此时只能回退到先下载整个 ZIP 再本地处理的方案。

【免费下载链接】minioMinIO is a high-performance, S3 compatible object store, open sourced under GNU AGPLv3 license.项目地址: https://gitcode.com/GitHub_Trending/mi/minio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询