如何确保我的用户正在下载新版本的S3文件?

时间:2014-12-04 09:47:21

标签: http caching amazon-s3 etag

这是在bash文件中:

s3cmd --add-header='Content-Encoding':'gzip' put /home/media/main.js s3://myproject/media/main.js

这是我将骨干压缩文件上传到Amazon S3的方法。 每次我更改我的javascript文件时都会运行此命令。

但是,当我在Chrome中刷新页面时,Chrome仍会使用缓存版本。

请求标题:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,es;q=0.6
AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.3
Cache-Control:max-age=0
Connection:keep-alive
Host:myproject.s3.amazonaws.com
If-Modified-Since:Thu, 04 Dec 2014 09:21:46 GMT
If-None-Match:"5ecfa32f291330156189f17b8945a6e3"
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36

回复标题:

Accept-Ranges:bytes
Content-Encoding:gzip
Content-Length:70975
Content-Type:application/javascript
Date:Thu, 04 Dec 2014 09:50:06 GMT
ETag:"85041deb28328883dd88ff761b10ece4"
Last-Modified:Thu, 04 Dec 2014 09:50:01 GMT
Server:AmazonS3
x-amz-id-2:4fGKhKO8ZQowKIIFIMXgUo7OYEusZzSX4gXgp5cPzDyaUGcwY0h7BTAW4Xi4Gci0Pu2KXQ8=
x-amz-request-id:5374BDB48F85796

请注意,Etag不同。我对它进行了更改,但是当我刷新页面时,这就是我得到的内容。 Chrome仍在使用我的旧文件。

3 个答案:

答案 0 :(得分:9)

看起来您的脚本已被Chrome本身或其他一些临时服务器主动缓存。

如果它是从HTML页面调用的js文件(听起来像是这样),我看到的一种技术是让页面为文件添加一个参数:

<script src="/media/main.js?v=123"></script>

<script src="/media/main.js?v=2015-01-03_01"></script>

...每次更新JS时都会更改(但服务器会忽略)。浏览器和任何临时缓存服务器都不会将其识别为相同,因此不会尝试使用缓存版本 - 即使在S3服务器上它仍然是相同的文件名。

每当您执行发布时,您可以更新此数字/日期/任何内容,理想情况下,如果模板引擎可以访问应用程序的版本号或ID,则可以自动更新。

这不是最优雅的解决方案,但如果你发现你使用了一个乐观的长缓存持续时间,它就很有用。

显然,这只有在你正确地将新文件上传到S3并且S3真正发送新版本的文件时才有效。尝试在javascript的网址上使用curlwget等命令行实用程序,以便在您对此有任何疑问时进行检查。

答案 1 :(得分:0)

失效方法

s3cmd -P --cf-invalidate put /home/media/main.js s3://myproject/media/main.js
       |    |
       |    Invalidate the uploaded filed in CloudFront.               
       |
      -P, --acl-public / Store objects with ACL allowing read for anyone.

这将使您指定的文件的缓存无效。也可以使整个站点无效,但是,上面的命令显示了我在这种情况下你想要的东西。

注意 :前1000个请求/月是免费的。之后,每个文件约为0.005美元,因此如果您执行大量无效请求,这可能是一个问题。

查询字符串/对象密钥方法

CloudFront在缓存对象时包含来自给定URL的查询字符串(来源)。这意味着即使你有相同的确切对象重复,但查询字符串不同,那么每个都将被缓存为一个不同的对象。为了使其正常工作,您需要在CloudFront控制台中为Yes选择Forward Query Strings,或在{{1}中指定true的值QueryString element当您使用CloudFront API时。

示例

DistributionConfig complex type

<强>摘要

确保提供对象的最方便的方法是当前将失效,但如果您不介意管理查询字符串参数,那么您应该发现它同样有效。在我看来,调整标题不会像上面任何一种方法那样可靠;客户端在很多方面处理缓存的方式不同,因此不容易区分缓存问题。

答案 2 :(得分:0)

您需要S3的响应才能包含Cache-Control标头。您可以在上传文件时设置:

s3cmd --add-header="cache-control:max-age=0,no-cache" put file s3://your_bucket/

我的例子中缺少空格和大写是由于s3cmd的一些奇怪的签名问题。您的里程可能会有所不同。

使用该命令更新文件后,您应该在S3响应中获取Cache-Control标头。