HTACCESS图片缓存规则,检查图片修改时间

3
我会提供两种不同的方式来服务图片:
  1. 例如,对于个人资料照片,我使用PHP脚本
  2. 对于图标和背景等,直接指向它们
目前正在妥善处理它们的缓存,而我在这方面是完全新手。
对于PHP脚本,我只需要在响应中添加一个“Last-Modified”头,并在再次调用时传递一个“304状态码”,如果文件没有更改(使用filemtime())。
对于直接访问,我使用HTACCESS,但迄今为止我看到的每个规则都不能像我的PHP脚本那样进行检查(检查文件是否已更改,然后提供304或文件本身)。
这是我计划使用的HTACCESS规则:
Header unset Pragma
FileETag None
Header unset ETag

# cache images/pdf docs for 10 days
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
  Header set Cache-Control "max-age=864000, public, must-revalidate"
  Header unset Last-Modified
</FilesMatch>

据我所知,更新缓存图像的唯一方法是将其重新命名。是否有绕过此问题的方法?例如,通过检查图像的最后修改日期?

唯一的方法确实是改变URL。您可以在URL中添加版本号,使其变成类似于/images/sample.jpg?v=2的形式。您可以使用一些重写规则来创建更美观的URL,例如/images/v2/sample.jpg。但是,如果图像没有更改,您必须小心不要更改URL,因为新的URL将无法与304一起使用。 - Gerben
你有没有尝试过 mod_expires - Gumbo
3个回答

2
如果可用,您可以使用mod_expires
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
  ExpiresDefault "modification plus 10 days"
</FilesMatch>

那么服务器应该回答什么呢?你具体在寻找什么?在修改后,10天内的响应是最新的,那之后呢? - Gumbo
这就是我在问题中解释的内容,我使用两种不同的方式处理缓存:使用PHP和使用Apache(因此使用htaccess,因为我无法访问httpd.conf)。我的PHP脚本总是回答304(=告诉使用缓存),除非文件与缓存中的文件不同。但是我不知道如何用Apache做同样的事情,我只知道一种方法(您写的方法)可以使缓存文件在一段时间后过期,而不是在修改后立即过期。我不知道我是否表达清楚了:/ - aaaaaa
我被说服了它不是这样,只是根据我所读到的.. 让我运行一些测试,然后再回来给您。 - aaaaaa
mod_expires仅实现过期模型。如果您想要防止这种情况,您需要使用不同的验证方式。这就是您可以使用mod_headers发送额外的Cache-Control指令的地方。 - Gumbo
你是只尝试了我的建议还是与你当前的配置一起尝试了呢? - Gumbo
显示剩余6条评论

1

你使用PHP所做的事情应该由Apache自动处理静态文件。它会设置Last-Modified头,并在请求中找到If-Modified-Since时响应304。这是自动完成的,与缓存无关。它不会阻止对您的服务器的重复请求,只会通过返回仅304信息而不是整个文件来节省带宽(和用户的加载时间),当文件未被修改时。

为了防止这些对您的服务器的重复请求,浏览器(和代理服务器)必须进行一些缓存。您可以通过HTTP标头或HTML中的META标签控制缓存。当您指定文件可缓存1周时,浏览器将在1周内不尝试联系您的服务器(尽管大多数浏览器都设置为在启动后首次访问时重新验证缓存条目)。

因此,您要么接受某些用户可能会使用旧的缓存副本一段时间(取决于到期标头),要么必须像Gerben建议的那样更改URL。只有这样,您才可以100%确保每个人都会获得新版本(这对于JavaScript很重要,因为一些旧的js文件和一些新的js文件可能会产生非常奇怪的错误)。现在几乎每个高性能网站都使用“file.ext?v=3”方法,以便他们可以将到期标头设置为长达6个月的大值。


实际上,HTML元标签不会被代理服务器抓取,因此最好使用头部信息。 - aaaaaa

1
正如 @Gumbo 指出的那样,“Apache应该已经为静态文件做到了这一点”。这是真的,Apache确实做到了,所以这种东西可以很好地工作:
<FilesMatch "\.(ico|pdf|jpg|jpeg|png|gif)$">
    Header set Cache-Control "max-age=864000, public, must-revalidate"
</FilesMatch>

附言:抱歉 @Gumbo,但我要求您更改您的答案以便我可以接受它,但您不愿意这样做,最终我不得不关闭那个问题。


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