我使用PHP库生成了一些图片。
有时候浏览器无法加载新生成的文件。
我如何仅针对动态创建的图像禁用缓存?
注意:我必须一直使用相同的名称来创建这些图像。
解决这个问题的常见且简单的方案,感觉像是一个技巧,但相当具有可移植性,那就是为每个请求动态图像添加一个随机生成的查询字符串。
例如:
<img src="image.png" />
将会变成什么
<img src="image.png?dummy=8484744" />
或
<img src="image.png?dummy=371662" />
从Web服务器的角度来看,访问的是同一个文件,但从浏览器的角度来看,无法执行任何缓存操作。
随机数生成可以在服务器上在提供页面时进行(只需确保页面本身未被缓存...),也可以在客户端上使用JavaScript进行。
您需要验证您的Web服务器是否能够处理此技巧。
通过HTTP头,可以控制浏览器缓存策略。请记住,它们只是一个提示。由于浏览器在这个(以及其他任何)领域都非常不一致,因此您需要多个头来在各种浏览器上获得所需的效果。
header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");
方案1并不理想。虽然它可以工作,但将hacky随机或带时间戳的查询字符串添加到图像文件的末尾会使浏览器重新下载和缓存每个图像的每个版本,每次加载页面时都会发生,无论图像在服务器上是否已更改。
方案2毫无用处。向图像文件添加nocache
标头不仅非常难以实现,而且完全不切实际,因为它要求您提前预测何时需要它,第一次加载您认为可能在未来的某个时间点可能更改的任何图像。
我发现的绝对最好的方法是在您的图像目录中使用ETAGS文件内的.htaccess文件。以下内容告诉Apache在图像文件标头中发送唯一的哈希值给浏览器。当图像文件被修改时,此哈希值仅会更改一次,并且此更改将触发浏览器在下一次请求图像时重新加载图像。
<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>
如果您需要在浏览器中使用JavaScript动态执行此操作,这里是一个示例...
<img id=graph alt=""
src="http://www.kitco.com/images/live/gold.gif"
/>
<script language="javascript" type="text/javascript">
var d = new Date();
document.getElementById("graph").src =
"http://www.kitco.com/images/live/gold.gif?ver=" +
d.getTime();
</script>
我检查了所有答案,最好的答案似乎是这个(但它并不是最好的):
<img src="image.png?cache=none">
起初。
但是,如果您添加了cache=none参数(即静态的“none”单词),它不会对任何事情产生影响,浏览器仍然从缓存加载。
解决这个问题的方法是:
<img src="image.png?nocache=<?php echo time(); ?>">
您基本上需要添加Unix时间戳以使参数动态且无缓存,这样它就有效了。
然而,我的问题有点不同:我正在加载即时生成的php图表图像,并使用$_GET参数控制页面。当URL GET参数保持不变时,我希望从缓存中读取图像,而在GET参数更改时不进行缓存。
为了解决这个问题,我需要对$_GET进行哈希处理,但由于它是数组,所以这里是解决方案:
$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";
编辑:
虽然上述解决方案完全有效,但有时候您希望在文件更改之前提供缓存版本。 (使用上述解决方案会完全禁用该图像的缓存)因此,要从浏览器中提供缓存的图像,直到图像文件发生更改,请使用:
echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";
filemtime() 函数用于获取文件的修改时间。
我知道这个话题很老,但它在谷歌上排名很高。我发现将此放在您的页眉中效果很好;
<meta Http-Equiv="Cache-Control" Content="no-cache">
<meta Http-Equiv="Pragma" Content="no-cache">
<meta Http-Equiv="Expires" Content="0">
<meta Http-Equiv="Pragma-directive: no-cache">
<meta Http-Equiv="Cache-directive: no-cache">
我正在寻找一个解决方案,上面的答案在我的情况下没有用(而我声望不足以对它们进行评论)。结果发现,至少对于我的用例和我使用的浏览器(Mac上的Chrome),唯一似乎能防止缓存的是:
Cache-Control = 'no-store'
为了完整性,我现在使用了 'no-cache, no-store, must-revalidate' 这三个指令。
因此,在我的情况下(在 Python 的 Flask 中动态生成图像),我必须按照以下步骤进行,以便能够在尽可能多的浏览器中工作......
def make_uncached_response(inFile):
response = make_response(inFile)
response.headers['Pragma-Directive'] = 'no-cache'
response.headers['Cache-Directive'] = 'no-cache'
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response
example.jpg?646413154
<?php
$filename = "path/to/images/example.jpg";
$filemtime = filemtime($filename);
?>
<img src="images/example.jpg?<?php echo $filemtime; ?>" >
var newtags='<div class="addedimage"><h5>preview image</h5><img src="'+one+'?nocache='+Math.floor(Math.random() * 1000)+'"></div>';
http://example.com/images/image.jpg?t=123456
其中“t=123456”是根据当前时间生成的时间戳或随机数。每次您更改查询字符串参数时,浏览器都会认为它是另一个图像,并重新加载它。 - Philibert Perusse