我有一个问题,用户报告他们的图像没有被上传并且旧的图像仍然存在。仔细检查后,新图像就在那里,它们只是与旧图像具有相同的名称。我在上传时所做的是重命名图像以用于 SEO 目的。当他们删除图像时,旧索引变得可用并被重复使用。因此,它具有相同的图像名称。
有没有办法(我想可能有一个元标记)告诉浏览器不要使用它的cahce?
更好的答案是将图像重命名为全新的名称。我会着手解决这个问题,但与此同时,当我解决更大的问题时,这是一个快速的解决方案。
附加一个带有任意唯一编号(或时间、或版本号等)的查询字符串:
<img src="image.png?80172489074" alt="a cool image" />
由于 URL 不同,这将导致一个新的请求。
这很难。您确实希望缓存图像,但是一旦有新图像可用,您就不想缓存它们:
使用带有过去日期的 expires 标头可以防止任何缓存。坏的
添加“缓存破坏”参数 ?342038402 可以解决问题,但也可以防止图像被缓存,这不是您想要的。坏的。
使用短的(比如说 1 小时)expires 标头会更好......一个小时后,用户将看到图像,但您的网络服务器不必每次都提供它。妥协,但什么时间有效?实在不可行。
解决方案?我能想到两个不错的选择:
查看 eTag 以及您使用它们的能力。这些是针对这种情况设计的。浏览器将明确询问您的服务器文件是否是最新的。如果你没有它,你可以在 apache 中打开它。
为每个新图像创建一个新 URL(并使用远期过期标头)。这就是你正在做的事情。
“添加一个“缓存破坏”......不好。”这不是真的,它会强制浏览器为图像缓存这个特定的版本,所以 image.png?342038402 将被缓存为那个版本。如果您有相同的图像和不同的查询字符串,那就不好了。
filemtime(string $filename)
函数与“缓存破坏”参数结合使用。这样,该文件的 URL 每次都会更改,请求的文件已更改。 (感谢 Michael Krelin - 黑客)。
我最喜欢的 PHP 解决方案:
<img src="<?php echo "image.jpg" . "?v=" . filemtime("image.jpg"); ?>" />
文件的每次更改“创建”文件的新版本
将当前日期时间附加到图像 src:
<img src="yourImage.png?v=<?php echo Date("Y.m.d.G.i.s")?>" />
您可以将 http-equiv
放在 <meta>
标记中,这将告诉浏览器不要使用缓存(甚至更好 - 以某种定义的方式使用它),但最好将服务器配置为发送正确的 http cache
标头。查看article on caching。
尽管如此,一些浏览器可能不支持所有的 http
标准,但我相信这是要走的路。
去随机。只需使用一些随机数并将其附加图像文件名即可。
<img src="image.jpg?<?=rand(1,1000000)?>">
另一个强大的解决方案:
<img src="image.png?v=<?php echo filemtime("image.png"); ?>" />
这会在路径上打印“last-modification-timestamp”。
新版本 --> 下载新镜像
相同的版本 --> 取缓存的一个
您可以通过使用 HTTP 标头来控制缓存行为。
过去设置 expires 标头将强制浏览器不使用缓存版本。
Expires: Sat, 26 Jul 1997 05:00:00 GMT
您可以查阅 RFC 了解更多详情。
如果您查看浏览器和服务器之间交换的数据,您会看到浏览器将发送一个 HTTP HEAD 请求以获取图像。结果将包含修改时间(但不包含实际图像数据)。如果服务器上的图像发生更改并且浏览器应再次下载图像,请确保此时间更改。
GET
请求中使用 If-Modified-Since
标头。结果还是一样——确保你正确地报告了文件的修改时间,这样缓存失效才能正常工作。
在 PHP 中你可以使用这个技巧
<img src="image.png?<?php echo time(); ?>" />
time() 函数显示当前时间戳。每个页面加载都是不同的。所以这段代码欺骗了浏览器:它读取了另一个路径,并且它“认为”自从用户上次访问该站点以来图像发生了变化。它必须重新下载它,而不是使用缓存之一。
听起来更关心的是主要用户看到他们的新图像而不是缓存被完全禁用?如果是这种情况,您可以执行以下操作:
var headers = new Headers()
headers.append('pragma', 'no-cache')
headers.append('cache-control', 'no-cache')
var init = {
method: 'GET',
headers: headers,
mode: 'no-cors',
cache: 'no-cache',
}
fetch(new Request('path/to.file'), init)
如果您在上传新图像后执行此操作,浏览器应该会看到这些标头并调用后端,跳过缓存。新图像现在在该 URL 下的缓存中。主要用户将看到新图像,但您仍然保留缓存的所有好处。一旦他们的缓存失效,任何其他查看此图像的人都会在一天左右的时间内看到更新。
如果更关心的是确保所有用户都能看到最新版本,那么您可能希望使用其他解决方案之一。
在 PHP 中,您可以发送一个随机数或当前时间戳:
<img src="image.jpg?<?=Date('U')?>">
或者
<img src="image.jpg?<?=rand(1,32000)?>">
结果不好,我认为这是正确编程的方法。
<td><?php echo "<img heigth=90 width=260 border=1 vspace=2 hspace=2 src=".$row['address']."?=".rand(1,999)."/>" ?></td>
前段时间我就提出过这个问题。我正在通过 AJAX 中的 JSON 获取数据。所以我所做的是,我只是添加了一个 Math.random() Javascript 函数,它就像一个魅力。我使用的后端是一个烧瓶。