TT Lab
开始
学习 学习路径 课程

对象存储与 S3

用 aws CLI 操作桶与对象

在 TT Lab 中继续学习

目标

用 aws CLI 熟悉 S3 兼容存储的基本操作——profile、存储桶、对象上传、前缀、列表、ETag、复制、元数据——并切身体会对象存储中没有目录这一事实。

为什么重要

理解 S3 API,并不是在学习某个特定厂商的产品。AWS S3、SeaweedFS、Garage、Ceph RGW、MinIO 说的全是同一套 API,所以这套 API 实际上就是一个可移植层。2025–2026 年 MinIO 社区版停止发布时,应用侧的迁移成本并不高,原因正在于此——只要更换端点和凭据,代码基本可以原样保留。本实验环境也经历了同样的事:服务器从 MinIO 换成了 SeaweedFS 的 S3 网关,但在这里输入的命令,放到 AWS 上一个字符都不用改就能运行。本实验特别要记住的是第 6 步的 ETag。单分段上传的 ETag 就是内容的 md5,因此客户端可以自行验证上传是否完整。在下一项实验中讲到分段上传的 ETag 与此有何不同时,这里学到的规则就是出发点。

步骤

  1. 用 aws configure set 向 profile local 写入四个值——aws_access_key_id、aws_secret_access_key、region、endpoint_url(http://127.0.0.1:9000)。凭据在 /opt/fixtures/s3/creds.env 中。aws --profile local s3 ls 必须无错误地结束。
  2. 创建存储桶 lab-media。它必须出现在 aws --profile local s3 ls 的列表中。
  3. 把 /opt/fixtures/s3/logo.png 上传为 s3://lab-media/img/logo.png。
  4. 把 /opt/fixtures/s3/ 中的 banner.png 上传为 img/banner.png,readme.txt 上传为 doc/readme.txt,sales.csv 上传为 doc/sales.csv。
  5. 把 aws --profile local s3 ls --recursive s3://lab-media 的结果保存到 /root/s3/list.txt。必须恰好是 4 行。
  6. 在 /root/s3/etag.txt 中写入 etag=<값> 和 md5=<값>(占位符均为具体的值)两行。logo.png 的 ETag(去掉引号)必须与本地文件的 md5 相同。
  7. 把 doc/readme.txt 以服务端复制的方式复制为 doc/README.txt,然后删除原对象。aws --profile local s3 ls s3://lab-media/doc/ 中必须只有 README.txt,而没有 readme.txt。
  8. 用 text/csv Content-Type 重新上传 sales.csv。aws --profile local s3api head-object --bucket lab-media --key doc/sales.csv 的输出中,ContentType 必须是 text/csv。

参考

设置 S3 profile

用 aws configure set 向 profile local 写入 aws_access_key_id、aws_secret_access_key、region、endpoint_url(http://127.0.0.1:9000)四个值。凭据在 /opt/fixtures/s3/creds.env 中。aws --profile local s3 ls 必须无错误地结束。

把端点和凭据绑定到同一个 profile 中。凭据在 /opt/fixtures/s3/creds.env 里;如果漏掉 endpoint_url,CLI 就会尝试连接真正的 AWS。

创建存储桶

创建存储桶 lab-media。它必须出现在 aws --profile local s3 ls 的列表中。

存储桶名称遵循 DNS 规则——只能使用小写字母、数字和连字符。

上传一个对象

把 /opt/fixtures/s3/logo.png 上传为 s3://lab-media/img/logo.png。

同时指定本地路径和目标键。目标键中的斜杠不是文件夹,而是名称的一部分。

用前缀来整理

把 /opt/fixtures/s3/ 中的 banner.png 上传为 img/banner.png,readme.txt 上传为 doc/readme.txt,sales.csv 上传为 doc/sales.csv。

分别上传到 img/ 和 doc/ 之下。实际上并不会创建文件夹,只是键名变成了那个样子。

导出递归列表

把 aws --profile local s3 ls --recursive s3://lab-media 的结果保存到 /root/s3/list.txt。必须恰好是 4 行。

默认列表会按前缀折叠显示。有一个选项可以全部展开。

比较 ETag 与本地哈希

在 /root/s3/etag.txt 中写入 etag=<값> 和 md5=<값>(占位符均为具体的值)两行。logo.png 的 ETag(去掉引号)必须与本地文件的 md5 相同。

单分段上传的 ETag 就是内容的 md5。把两个值并排写出来进行比较。

服务端复制后删除原对象

把 doc/readme.txt 以服务端复制的方式复制为 doc/README.txt,然后删除原对象。aws --profile local s3 ls s3://lab-media/doc/ 中必须只有 README.txt,而没有 readme.txt。

没有重命名操作。先复制再删除,就是重命名。要让它在服务器上处理,不要经过下载。

指定 Content-Type 上传并确认

用 text/csv Content-Type 重新上传 sales.csv。aws --profile local s3api head-object --bucket lab-media --key doc/sales.csv 的输出中,ContentType 必须是 text/csv。

虽然也会根据扩展名推测,但明确指定更稳妥。查询对象元数据来确认。