禁用某些图像的缓存

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

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

我如何才能禁用缓存只为图像动态创建我?

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

206363 次浏览

浏览器缓存策略可以由 HTTP 头控制。记住,它们只是一个暗示,真的。由于浏览器在这个(和任何其他)领域都非常不一致,因此需要几个标头才能在一系列浏览器上获得所需的效果。

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

这个问题的一个常见和简单的解决方案是向每个动态映像请求添加一个随机生成的查询字符串。

所以,例如-

<img src="image.png" />

会变成

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

或者

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

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

随机数生成可以发生在服务器上(只要确保页面本身没有被缓存...) ,也可以发生在客户机上(使用 JavaScript)。

您需要验证您的 Web 服务器是否能够处理这个技巧。

如果您需要在浏览器中使用 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>

我已经用它来解决类似的问题... 显示一个图像计数器(从外部提供商)。它并不总是正确刷新。在添加了一个随机参数之后,所有工作都很正常:)

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

示例代码(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

我知道这个话题很老了,但它在谷歌上排名很好。我发现把这个放在你的页眉上效果很好;

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

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

最好是添加一个校验和,例如图像所表示的数据。这样可以在可能的情况下进行缓存。

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

首先,必须让 apache 将 jpg 作为 php 进行处理。 看这里: 可以用扩展名 file.PHP.jpg 执行 PHP 吗?

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

然后用 image jpeg 函数输出图像。

请注意,让 php 处理 jpg 图像是非常不安全的。还请注意,我还没有测试这个解决方案,所以它是由你使其工作。

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

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

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

我的工作。

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

<img src="image.png?cache=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 ()获取文件修改时间。

让我们把另一个解决方案加到一起。

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

example.jpg?646413154

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

当图像被更新时,电影时间将被更改。

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

现在输出图像:

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

解决方案1不是很好。它确实可以工作,但是在你的图片文件末尾添加随机的或者有时间戳的查询字符串会让浏览器重新下载并缓存每个图片的每个版本,每次加载一个页面,不管服务器上的图片是否已经改变。

解决方案2是没用的。将 nocache头文件添加到图像文件中不仅非常难以实现,而且完全不切实际,因为它要求您在第一次加载任何您认为 可能将在未来某个时刻更改的图像时使用 提前预测什么时候需要

进入 Etag..。

我发现解决这个问题的 绝对是最好的方式是在您的图像目录中使用 在.htaccess 内部的 ETAGS 文件。下面告诉 Apache 向图像文件头中的浏览器发送一个惟一的散列。此哈希只有在修改图像文件时才会发生更改,这种更改会触发浏览器在下次请求图像时重新加载该图像。

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

我只是在寻找一个解决方案,上面的答案在我的案例中不起作用(我没有足够的声誉来评论它们)。事实证明,至少对于我的用例和我正在使用的浏览器(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

我遇到了这个问题,就这样克服了。

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