禁用某些图像的缓存

dol*_*oug 99 html caching image

我使用PHP lib生成一些图像.

有时浏览器不会加载新生成的文件.

如何为我动态创建的图像禁用缓存?

注意:随着时间的推移,我必须为创建的图像使用相同的名称.

Hex*_*gon 211

这个问题的常见且简单的解决方案感觉像是黑客但相当便携,是为动态图像的每个请求添加一个随机生成的查询字符串.

所以,例如 -

<img src="image.png" />
Run Code Online (Sandbox Code Playgroud)

会成为

<img src="image.png?dummy=8484744" />
Run Code Online (Sandbox Code Playgroud)

要么

<img src="image.png?dummy=371662" />
Run Code Online (Sandbox Code Playgroud)

从Web服务器的角度来看,访问相同的文件,但是从浏览器的角度来看,不能执行缓存.

随机数生成可以在服务页面时在服务器上发生(只是确保页面本身没有缓存...),或者在客户端上(使用JavaScript).

您需要验证您的Web服务器是否可以应对此技巧.

  • 使用数据更改的时间戳或反射数据的版本号,而不是随机数. (81认同)
  • 请注意:您实际上并没有阻止浏览器缓存图像,您只能阻止查看缓存的图像.对图像应用合适的标题是imho的最佳方式(参见下面的lhunath解决方案).从这种方式来说,您还可以不必要地使用不想缓存的映像填充缓存,其成本是为实际上想要缓存的内容创建更少的缓存空间. (17认同)
  • http://stackoverflow.com/questions/126772/how-to-force-a-web-browser-not-to-cache-images (3认同)
  • 这实际上不起作用,图像需要以另一种方式刷新(通常在图像裁剪时,图像保持不变) (2认同)

lhu*_*ath 41

浏览器缓存策略可以通过HTTP标头控制.请记住,它们只是一个暗示,真的.由于浏览器在此(以及任何其他)字段中非常不一致,因此您需要多个标头才能在一系列浏览器上获得所需的效果.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");
Run Code Online (Sandbox Code Playgroud)

  • @Thorpe:它适用于HTTP响应.回复中包含的内容无关紧要.无论是图像数据,HTML数据还是其他任何内容.如果它不起作用,你可能没有做对.检查响应中的HTTP标头,看看它们是否已正确分配. (5认同)
  • 这将应用于整个页面....我无法仅禁用一张图像的缓存(该页面中的特定图像)? (2认同)
  • @PawelKrakowiak请注意,添加标题不适用于已经缓存*的图像,因为浏览器甚至不向服务器询问它们,因此永远不会看到标题.它们适用于添加后的任何图像请求. (2认同)
  • 此解决方案仅适用于程序员,而不适用于Web设计人员。我想指出这一点,因为除非它们本身是用编程语言生成图像的,否则就不能打开图像并在图像中添加标题,这似乎会使注释者感到困惑。 (2认同)

cro*_*lee 12

解决方案1并不好.它确实有效,但在图像文件的末尾添加hacky随机或带时间戳的查询字符串是不可扩展的,并且会使浏览器重新下载并缓存您发送的每个图像的每个版本.

解决方案2没用.nocache标题添加到图像文件不仅非常难以实现,而且完全不切实际,因为它需要您预先确定何时需要它,第一次加载您认为可能在将来的某个时刻发生变化的任何图像.

输入Etags ...

我发现解决此问题的绝对最佳方法是在images目录中的.htaccess文件中使用ETAGS.以下内容告诉Apache在映像文件头中向浏览器发送唯一的哈希值.此哈希值仅在修改图像文件的时间后发生变化,此更改会在下次请求时触发浏览器重新加载图像.

<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>
Run Code Online (Sandbox Code Playgroud)


小智 10

如果你需要使用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>
Run Code Online (Sandbox Code Playgroud)


Tar*_*rik 9

我检查了所有的答案,最好的答案似乎是(不是):

<img src="image.png?cache=none">
Run Code Online (Sandbox Code Playgroud)

首先.

但是,如果添加cache = none参数(这是静态的"无"字),它不起作用,浏览器仍然从缓存加载.

解决这个问题的方法是:

<img src="image.png?nocache=<?php echo time(); ?>">
Run Code Online (Sandbox Code Playgroud)

你基本上添加unix时间戳来使参数动态而没有缓存,它起作用了.

但是,我的问题有点不同:我正在加载生成的php图表图像,并使用$ _GET参数控制页面.我希望当URL GET参数保持不变时从缓存中读取图像,并且在GET参数更改时不缓存.

要解决这个问题,我需要哈希$ _GET,但因为它是数组,所以解决方案是:

$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";
Run Code Online (Sandbox Code Playgroud)

编辑:

虽然上面的解决方案工作正常,但有时您希望提供缓存版本UNTIL文件更改.(使用上面的解决方案,它会完全禁用该图像的缓存)因此,要从浏览器UNTIL提供缓存图像,图像文件的使用会发生变化:

echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";
Run Code Online (Sandbox Code Playgroud)

filemtime()获取文件修改时间.


小智 6

我知道这个话题很老了,但它在谷歌中的排名非常好。我发现将其放入标题中效果很好;

<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">
Run Code Online (Sandbox Code Playgroud)


小智 5

我只是在寻找解决方案,上面的答案在我的情况下不起作用(我没有足够的声誉来评论它们)。事实证明,至少对于我的用例和我使用的浏览器(OSX 上的 Chrome),似乎唯一阻止缓存的是:

Cache-Control = 'no-store'
Run Code Online (Sandbox Code Playgroud)

为了完整起见,我现在使用所有 3 个“无缓存、无存储、必须重新验证”

因此,在我的情况下(在 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
Run Code Online (Sandbox Code Playgroud)