如何仅当服务器中的文件发生更改时,在 Apache 中使图像过期并强制重新加载

如何仅当服务器中的文件发生更改时,在 Apache 中使图像过期并强制重新加载

我有一个在 Apache2 服务器上运行的 PHP 应用程序。我使用 HTML5 Boilerplate 开始,其中.htaccess包含所有图像的“1 个月”到期策略。例如:

ExpiresByType image/jpeg                            "access plus 1 month"

我的应用程序还允许用户用新图像(使用相同的名称和路径)替换现有图像。但是,替换后,用户仍会看到旧图像,直到页面被强制刷新(例如Ctrl- F5)。

我从日志中注意到,从技术上讲,由于图像设置为 1 个月后过期,因此浏览器不会向服务器请求该图像。只有在强制刷新时,浏览器才会请求该图像,此时 Apache2 可能会发出304(如果文件从未更改) 或发送带有200(如果文件已更改) 的新图像。

我想要的是一个简单直接的机制来:

  • 保留现有设置,图片将在 1 个月后过期。如果浏览器已经拥有该图片,则无需再次获取。
  • 但如果用户更新了图片,浏览器就会自动获取新图片。无需告诉用户强制刷新。
  • 新图像的获取还必须扩展到最后一点之后的其他用户或其他浏览器。

作为备选,如果我可以有条件地将过期策略设置为仅针对特定路径的“立即”,我不会介意(其他文件夹中的图像必须遵循一般过期策略)。304我想我可以忍受大量的 s。

我不想简单地将文件名更改为新文件名。文件名是动态生成的,并且有多个 - 跟踪它们的“新名称”会增加复杂性。(尽管如果没有其他简单的解决方案,我将不得不探索这一点。)

答案1

你要求太多了:明确配置某些数据的有效期为一个月,但你改变主意后它就失效了。一般来说,你必须下定决心。

  • 如果 304 错误没有对你造成伤害:缩短间隔可能是一个解决方案
  • 解决此问题的常用方法涉及图像的时间戳参数:不要加载logo.png,而是加载logo.png?t=20160327083700时间戳在整个应用程序中是静态的(并根据您的判断进行更新)或文件的最后更改日期(这会增加服务器端负担)
  • 按照您的评论,您可能还会成功在路径的其他位置添加时间戳(以便您的图像名称保持不变):。/20160327083700/logo.png但是,请阅读我关于过早优化的最后一段

只要您告诉所有人某种资源在很长一段时间内有效,您就不会惊讶于他们会相信您的话并重复使用它直到有效期结束。

对于上面的时间戳参数,我使用了一个可读性较高的时间戳(例如今天)。您可能只想使用自 1970 年以来未格式化的毫秒数或任何您容易获得的未格式化值。它只需要随着文件的每次更新而改变。

编辑:正如您在评论中所述,浏览器倾向于将?URL 中的 解释为缓存绕过 - 并且最好尽早再次请求资源。因此,您最好的选择可能是缩短时间跨度。特别是当您说您将度过 304 时:缩短到"access plus 1 hour"(甚至 10 分钟)。无论如何,这都是正确的做法:状态内容可以缓存 1 个月当且仅当可缓存1个月。

顺便说一句,让我提醒你一句老话“过早优化是万恶之源”——我敢打赌,这句话"access plus 1 month"不是来自任何性能调优会议,而是来自你的猜测。而且,正如你在这个问题中看到的那样,这种过早的优化实际上会导致很多做额外的工作来解决它所引起的冲突。

相关内容