自动为整个 S3 存储桶设置缓存控制(使用存储桶策略)?

169

我需要为整个S3存储桶设置缓存控制头信息,包括现有的和将来上传的文件,并希望通过存储桶策略进行设置。

我知道如何编辑现有的缓存控制头信息,并且知道如何在自己上传文件时指定这些头信息,但不幸的是,上传文件的应用程序无法设置这些头信息,因为它使用S3fs将文件复制到S3中。


1
对于任何想要在CloudFront分发上设置cache-control: max-age的人,请参考这个帖子中的答案; 对于通过aws s3推送资源的任何人,另一种解决方案是通过--cache-control max-age=设置一个值。 - Fabien Snauwaert
11个回答

266

现在有3种方法可以完成此操作:通过AWS控制台通过命令行通过s3cmd命令行工具


AWS控制台说明

这是目前推荐的解决方案。它很简单,但可能需要一些时间。

  • 登录AWS管理控制台
  • 进入S3存储桶
  • 按路径选择所有文件
  • 从菜单中选择“更多”
  • 选择“更改元数据”
  • 在“键”字段中,从下拉菜单中选择“Cache-Control”,为Value输入max-age=604800(7天)
  • 点击“保存”按钮

(感谢@biplob - 请给他一些爱)


AWS命令行解决方案

最初,当我创建这个存储桶时,策略是不可行的,所以我想到了如何使用aws-cli来完成它,而且非常流畅。在研究时,我找不到任何实际应用的例子,所以我想发布一些我的解决方案,以帮助有需要的人。

注意:默认情况下,aws-cli仅复制文件的当前元数据,即使您指定了新元数据。

要使用在命令行上指定的元数据,需要添加“--metadata-directive REPLACE”标志。以下是一些示例。

对于单个文件

aws s3 cp s3://mybucket/file.txt s3://mybucket/file.txt --metadata-directive REPLACE \
--expires 2034-01-01T00:00:00Z --acl public-read --cache-control max-age=2592000,public

对整个存储桶进行操作(注意--recursive标志):

aws s3 cp s3://mybucket/ s3://mybucket/ --recursive --metadata-directive REPLACE \
--expires 2034-01-01T00:00:00Z --acl public-read --cache-control max-age=2592000,public

我发现一个小问题,如果你只想针对特定的文件类型进行应用,你需要排除所有的文件,然后再包括你想要的那些。

仅限于jpg和png文件:

aws s3 cp s3://mybucket/ s3://mybucket/ --exclude "*" --include "*.jpg" --include "*.png" \
--recursive --metadata-directive REPLACE --expires 2034-01-01T00:00:00Z --acl public-read \
--cache-control max-age=2592000,public

如果您需要更多信息,请参考以下手册链接:

已知问题:

"Unknown options: --metadata-directive, REPLACE"

这可能是由于awscli版本过旧导致的 - 请参见下面@eliotRosewater的答案


S3cmd工具

S3cmd是一个“用于管理Amazon S3和CloudFront服务的命令行工具”。虽然此解决方案需要 git pull,但它可能是一种更简单、更全面的解决方案。

有关完整说明,请查看@ashishyadaveee11在下面发布的帖子



8
感谢提供实际的操作示例。仅通过阅读文档,我很难找到可行的方法。 - danneu
2
当我运行上述任何命令时,我会收到“未知选项:--metadata-directive,REPLACE”的错误提示。请帮帮我。 - user3722785
1
注意,现在有更简单的方法。您可以通过AWS控制台更改存储桶中所有文件的元数据。请参见CoderBoy下面的答案:https://dev59.com/cWkv5IYBdhLWcg3wqimS#47072736 - Martin Tschammer
2
请注意,使用 --meta-directive REPLACE 将覆盖未在命令中复制的任何先前元数据!例如,“content-encoding gzip”将在未明确添加到 cp 命令时被删除。 - Harmen Janssen
1
cp 命令是否会下载并重新上传所有内容? - mlissner
显示剩余11条评论

69

现在,可以轻松地从AWS控制台更改它。

  • 登录到AWS管理控制台
  • 进入S3存储桶
  • 通过路由选择所有文件
  • 从菜单中选择“更多”
  • 选择“更改元数据”
  • 在“键”字段中,从下拉菜单中选择“Cache-Control”
  • 输入 max-age=604800(7天)作为值
  • 按下“保存”按钮

执行时间取决于您的存储桶文件数量。 如果意外关闭浏览器,请重新开始操作。


13
“按路径选择所有文件”是什么意思? - Tamzin Blake
1
从您想要设置元数据的目录中选择所有/一些文件。 - biplob
1
这个操作会替换先前的元数据还是添加新的元数据?(我不想失去我所有的内容类型!) - Chris
1
max-age=604800 意味着设置缓存过期时间为7天。 - insivika
2
@Chris 它重置了我所有的内容类型(Content-Type: binary/octet-stream) UGH - Firsh - justifiedgrid.com
显示剩余3条评论

25

步骤

  1. 克隆代码库:git clone https://github.com/s3tools/s3cmd
  2. 运行 s3cmd --configure (你将被要求提供两个密钥 - 从确认电子邮件或亚马逊帐户页面复制并粘贴它们。复制时要小心!它们区分大小写,必须准确输入,否则您将继续收到有关无效签名或类似错误的错误消息。 记得为密钥添加 s3:ListAllMyBuckets 权限,否则在测试访问权限时将收到 AccessDenied 错误。)
  3. ./s3cmd --recursive modify --add-header="Cache-Control:public ,max-age= 31536000" s3://your_bucket_name/

非常好的答案。谢谢!有没有一种方法只更新那些还没有这个头设置的内容? - PKHunter
有人有类似的解决方案可用于Windows的S3Express吗? - Joe
你也可以使用Homebrew进行安装(https://github.com/s3tools/s3cmd/blob/master/INSTALL.md)。 - Rupert Rawnsley

16

我一直在苦苦思索这个问题,直到我找到并阅读了文档。在这里分享,以帮助其他人:

最终对我有效的命令是这个。我选择了 1 秒的过期时间进行测试,以验证预期结果:

aws s3 cp \
  --metadata-directive REPLACE \
  --cache-control max-age=1,s-maxage=1 \
  s3://bucket/path/file \
  s3://bucket/path/file
  • 当在S3上修改现有文件的元数据时,需要使用--metadata-directive REPLACE
  • max-age以秒为单位设置浏览器缓存时间
  • s-maxage以秒为单位设置CloudFront缓存时间

同样地,如果在上传到S3时设置这些Cache-Control头值,则命令将如下所示:

aws s3 cp \
  --cache-control max-age=1,s-maxage=1 \
  /local/path/file \
  s3://bucket/path/file

8
我认为您无法在存储桶级别指定此内容,但有几种解决方法可供您选择。
  1. 将对象复制到自身 在 S3 上设置适当的 cache-control 标头以进行复制操作。

  2. 在文件的 URL 中指定响应标头。您需要使用预签名 URL 才能使其正常工作,但您可以在查询字符串中指定某些响应标头,包括 cache-controlexpires。要获取可用选项的完整列表,请参见:http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectGET.html?r=5225


谢谢Geoff,我知道(1),但不知道(2)。这不是我所希望的(尽管我担心这是不可能的)。 - thattommyhall
您有一个 AWS CLI 命令的例子如何完成 #1 吗?http://docs.aws.amazon.com/cli/latest/reference/s3/cp.html - dpegasusm

5

你能提供一些如何创建这个Lambda的详细信息吗?听起来是一个很好的解决方案。 - Wouter
1
@Wouter 确定,我给你找到了一个链接,可以帮助你轻松实现目标,https://www.aaronfagan.ca/blog/2017/how-to-configure-aws-lambda-to-automatically-set-cache-control-headers-on-s3-objects/ 如果需要任何帮助或支持,我很乐意提供帮助。 - Ibrahim Bou Ncoula
我知道这很老了,但我发现这个资源对我正在寻找的东西非常有用。谢谢你提供这个资源,我的兄弟!点赞给你! - castaway2000

2
对于那些尝试使用Dan的答案并遇到错误的人: “未知选项:--metadata-directive, REPLACE” 我也遇到了这个问题,问题在于我使用sudo apt-get install awscli安装了awscli的旧版本,该版本缺少--metadata-directive命令。所以我使用sudo apt-get remove awscli将其删除。 然后按照亚马逊的程序重新安装: http://docs.aws.amazon.com/streams/latest/dev/kinesis-tutorial-cli-installation.html 唯一的区别是我不得不使用sudo -H因为权限问题,其他人可能也会遇到这个问题。

2
桶策略是为了给存储在桶内的对象和桶本身授权,因此这种方法不会产生您要寻找的结果。其他答案使用自动化手段修改对象元数据,但如果您愿意将存储桶放在 CloudFront 后面,也可以使用 Lambda@Edge。
使用 Lambda@Edge,您可以针对每个客户端请求运行任意代码,并且它可以更改从源(在本例中为 S3 桶)返回的标头。它需要更多的配置并且需要一些费用,但以下是解决方案的蓝图:
- 创建 CloudFront 分配 - 将 S3 存储桶添加为原始来源 - 创建修改响应标头的 Lambda 函数 - 使用 CloudFront 分配的 URL 访问文件
AWS 文档提供了如何修改响应标头的 示例。如果您恰好使用 Terraform 管理基础架构,我已经写了一篇 文章 如何操作。

1

之前的答案误导了我,所以我想分享一下我的使用方法。AWS CLI 只需要两个命令:

aws s3 cp s3://bucketname/ s3://bucketname/ --cache-control max-age=12345 --recursive

这是关于已经存在的内容,使用cp命令。设置--cache-control就可以了。
如果您要上传,也可以使用sync命令,命令如下:
aws s3 sync z:\source\folder s3://bucketname/folder --delete --cache-control max-age=12345 --acl public-read

请注意,我完全不使用 --metadata-directive,因为使用它会导致你猜测的内容类型丢失,这将使像图像之类的东西在浏览器中无法显示而立即下载。我的解决方案保留了猜测的值,并允许与同步一起猜测。

1

之前的回答或者与问题不太相符,或者会产生费用(Lambda)。

你应该在上传文件时设置“cache-control”头部(PutObject或MultiPartUpload)。

根据你使用的语言,具体操作可能有所不同。文档并不十分清晰(AWS希望你使用其他解决方案支付他们的费用)。

以下是PHP代码示例:

$uploader = new MultipartUploader ($s3,$filename,[
    ...,
    'before_initiate' => function(\Aws\Command $command){
        $command['CacheControl'] = 'max-age=31536000,public';
    },
...
]);

另一个使用 Go 的例子:
cc := "max-age=31536000,public"
input := &s3.PutObjectInput{
    ...,
    CacheControl: &cc,
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接