禁用某些图像的缓存


113

我使用PHP库生成一些图像。

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

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

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

Answers:


233

对于这个问题,一种常见而简单的解决方案是给每个对动态图像的请求添加一个随机生成的查询字符串,这种解决方案看起来很像黑客,但移植性很强。

因此,例如-

<img src="image.png" />

会成为

<img src="image.png?dummy=8484744" />

要么

<img src="image.png?dummy=371662" />

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

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

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


87
请使用数据更改的时间戳或反射数据的版本号,而不是随机数。
2009年


19
请注意:您实际上并没有阻止浏览器缓存图像,而只是阻止查看缓存的图像。将适当的标题应用于图像是恕我直言的最佳方法(请参阅下面的Lhunath解决方案)。通过这种方式,您还可以在不必要的情况下用不需要的图像填充缓存,但这样做的代价是导致您实际上想要缓存的内容占用更少的缓存空间。
乔斯

我相信本文可以解释这种行为的原因。
Metalcoder 2013年

1
这确实不起作用,需要使用另一种方法冲洗图像(通常在图像裁剪时,图像保持不变)
2015年

44

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

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");

1
这将应用于整个页面。...我不能仅对一个图像(该页面中的特定图像)禁用缓存吗?
dole doug

5
@Thorpe:它适用于HTTP响应。响应中包含的内容无关紧要。无论是图像数据,HTML数据还是其他数据。如果它不起作用,那么您可能做错了。检查响应中的HTTP标头,以查看是否已正确分配它们。
lhunath

我希望它能工作... Chrome没有任何问题,但是Firefox 14和IE 8即使发送了上述标头也拒绝刷新图像。与向查询字符串中添加一些任意参数相比,这本来是更清洁的解决方案。叹息
Pawel Krakowiak 2012年

2
@PawelKrakowiak请注意,添加标题不适用于已经缓存的图像,因为浏览器甚至不向服务器询问它们,因此将永远看不到标题。添加后,它们将适用于任何图像请求。
lhunath '16

2
此解决方案仅适用于程序员,而不适用于Web设计人员。我想指出这一点,因为除非它们本身是用编程语言生成图像的,否则就不能打开图像并在图像中添加标题,这似乎会使评论者感到困惑。
布鲁斯

12

如果您需要使用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>

12

解决方案1不好。它确实可以工作,但是在图像文件的末尾添加乱码或带有时间戳的查询字符串将使浏览器重新下载并缓存每次加载页面时每个图像的每个版本,无论天气如何变化在服务器上。

解决方案2没有用。nocache图像文件添加标头不仅很难实现,而且是完全不切实际的,因为它要求您预先预测何时需要它,这是第一次加载任何您认为将来可能会更改的图像时。

输入Etags ...

绝对最好的办法我已经找到解决这个是使用的ETag一个内部的.htaccess在你的图像目录中的文件。以下内容告诉Apache将唯一的哈希发送到图像文件标题中的浏览器。仅当修改图像文件时,此哈希值才会更改,并且此更改将触发浏览器在下次请求图像时重新加载图像。

<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>

11

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

<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()获取文件修改时间。


4

我知道这个话题很老,但是在Google中排名很高。我发现将其放在您的标头中效果很好;

<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">

不幸的是,现代浏览器忽略了这些指令,因此该解决方案可能仅在某些浏览器上有效,而且,它会禁用所有内容的缓存,而不仅限于特定图像
ZioCain

4

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

Cache-Control = 'no-store'

为了完整起见,我现在使用“无缓存,无存储,必须重新验证”的全部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

仅在响应中
保留

它不仅适用于Chrome,而且适用于Firefox。现在看来这是一个标准:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control(请参阅“ 防止缓存 ”部分)。
Gino Mempin

3

解决方案是更改图像源。您确实可以通过在图像上添加时间戳或随机数来做到这一点。

最好添加一个校验和,例如图像表示的数据。这将在可能的情况下启用缓存。


1

让我们添加另一种解决方案。

在末尾添加唯一的字符串是一个完美的解决方案。

example.jpg?646413154

以下解决方案扩展了该方法,并提供了缓存功能,并在更新映像时获取了新版本。

映像更新后,filemtime将更改。

<?php
$filename = "path/to/images/example.jpg";
$filemtime = filemtime($filename);
?>

现在输出图像:

<img src="images/example.jpg?<?php echo $filemtime; ?>" >

1
那是我使用的原因,因为它具有缓存有效性。
基因

1

我有这个问题,克服这样的问题。

var newtags='<div class="addedimage"><h5>preview image</h5><img src="'+one+'?nocache='+Math.floor(Math.random() * 1000)+'"></div>';

0

我用它来解决我的类似问题……显示一个图像计数器(来自外部提供商)。它始终无法正确刷新。并且在添加了随机参数之后,一切正常:)

我附加了日期字符串,以确保至少每分钟刷新一次。

示例代码(PHP):

$output .= "<img src=\"http://xy.somecounter.com/?id=1234567890&".date(ymdHi)."\" alt=\"somecounter.com\" style=\"border:none;\">";

这样就产生了如下src链接:

http://xy.somecounter.com/?id=1234567890&1207241014

0

如果您有一个硬编码的图像URL,例如:http : //example.com/image.jpg,则可以使用php向图像添加标题。

首先,您将必须使apache将您的jpg作为php处理。请参见此处: 是否可以使用扩展名file.php.jpg执行PHP?

从文件加载图像(imagecreatefromjpeg),然后添加先前答案的标题。使用php函数标头添加标头。

然后使用imagejpeg函数输出图像。

请注意,让php处理jpg图像非常不安全。另外请注意,我尚未测试此解决方案,因此您可以自行决定是否使用该解决方案。


-1

简单,发送一个标头位置。

我的网站包含一张图片,上传图片后没有任何变化,然后添加以下代码:

<?php header("Location: pagelocalimage.php"); ?>

工作适合我。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.