禁用某些图像的缓存

Posted

技术标签:

【中文标题】禁用某些图像的缓存【英文标题】:Disable cache for some images 【发布时间】:2010-10-18 05:39:09 【问题描述】:

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

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

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

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

【问题讨论】:

【参考方案1】:

解决方案 1 不是很好。它确实有效,但是在图像文件的末尾添加 hacky 随机或时间戳查询字符串会使浏览器重新下载并缓存每个图像的每个版本,每次加载页面时,无论天气如何,服务器上的图像都发生了变化。

解决方案 2 没用。nocache 标头添加到图像文件不仅很难实现,而且完全不切实际,因为它需要您预测何时需要它提前,第一次加载您认为在未来某个时间点会发生变化的任何图像。

输入标签...

我发现解决此问题的绝对最佳方法是在图像目录中的 .htaccess 文件中使用 ETAGS。下面告诉 Apache 在图像文件头中向浏览器发送一个唯一的散列。此哈希仅在修改图像文件时才会更改,并且此更改会触发浏览器在下次请求时重新加载图像。

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

【讨论】:

此解决方案是否适用于以前缓存的文件?【参考方案2】:

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

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

【讨论】:

这将适用于整个页面....我不能只为一个图像禁用缓存(该页面中的特定图像)? @Thorpe:它适用于 HTTP 响应。响应中包含的内容无关紧要。无论是图像数据、html 数据还是其他任何东西。如果它不起作用,你可能没有做对。检查响应中的 HTTP 标头,看看它们是否已正确分配。 我希望这可行... Chrome 没有任何问题,但 Firefox 14 和 IE 8 拒绝刷新图像,即使发送了上述标头。这比在查询字符串中添加一些任意参数要干净得多。 叹息 @PawelKrakowiak 请注意,对于已缓存的图像,添加标头将不起作用,因为浏览器甚至不会询问服务器有关它们的信息,因此永远不会看到标题。它们适用于您添加它们后提出的任何图像请求。 此解决方案适用于程序员,而非网页设计师。我想我会指出这一点,因为人们不能只打开图像并为图像添加标题,除非他们自己用编程语言生成图像,这似乎让评论者感到困惑。【参考方案3】:

我遇到了这个问题并像这样克服。

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

【讨论】:

【参考方案4】:

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

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

【讨论】:

【参考方案5】:

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

【讨论】:

仅仅在响应中加上 no-store 就足以让它为我工作 它不仅适用于 Chrome,也适用于 Firefox。它现在似乎是一个标准:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control(参见“防止缓存”部分)。【参考方案6】:

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

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

example.jpg?646413154

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

当图片更新时,filemtime 会发生变化。

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

现在输出图像:

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

【讨论】:

这是我使用的缓存有效性。【参考方案7】:

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

我的网站,包含一张图片,上传图片后没有变化,所以我添加了这段代码:

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

为我工作。

【讨论】:

【参考方案8】:

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

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

【讨论】:

【参考方案9】:

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

首先,您必须让 apache 将您的 jpg 处理为 php。 看这里: Is it possible to execute PHP with extension file.php.jpg?

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

然后用imagejpeg函数输出图片。

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

【讨论】:

【参考方案10】:

我知道这个话题很老,但它在 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">

【讨论】:

不幸的是,现代浏览器忽略了这些指令,因此该解决方案可能仅适用于某些浏览器,而且它会禁用所有内容的缓存,而不仅仅是特定图像【参考方案11】:

我用它来解决我的类似问题...显示图像计数器(来自外部提供商)。它并不总是正确刷新。添加随机参数后,一切正常:)

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

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

【讨论】:

【参考方案12】:

如果您需要在浏览器中使用 javascript 动态执行此操作,这里有一个示例...

<img id=graph  
  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>

【讨论】:

【参考方案13】:

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

所以,例如-

<img src="image.png" />

会变成

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

或者

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

从网络服务器的角度来看,访问的是相同的文件,但从浏览器的角度来看,无法执行缓存。

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

您将需要验证您的网络服务器是否可以应付这个技巧。

【讨论】:

使用数据更改的时间戳或反映数据的版本号,而不是随机数。 ***.com/questions/126772/… 请注意:您实际上并没有阻止浏览器缓存图像,您只是阻止查看缓存的图像。对您的图像应用适当的标题是最好的方法(见下面 lhunath 的解决方案)。由于这种方式,您还不必要地用您不想缓存的图像填充缓存,其代价是为您实际想要缓存的内容减少缓存空间。 我相信this article解释了这种行为的原因。 这个真的不行,图片需要用另一种方式刷新(通常在图片裁剪时,图片保持不变)

以上是关于禁用某些图像的缓存的主要内容,如果未能解决你的问题,请参考以下文章

Windows 7 Embedded - 以编程方式禁用磁盘缓存:

禁用或更改 Firefox 的元素/图像突出显示颜色

如何禁用 ASP.NET 中某些控件的 UpdateProgress?

你如何在Javascript中缓存图像

用于路径缓存的快速、无冲突哈希算法?

如何为作业禁用 GitLab 构建缓存