Html 如何强制 Web 浏览器不缓存图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/126772/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to force a web browser NOT to cache images
提问by Philibert Perusse
Background
背景
I am writing and using a very simple CGI-based (Perl) content management tool for two pro-bono websites. It provides the website administrator with HTML forms for events where they fill the fields (date, place, title, description, links, etc.) and save it. On that form I allow the administrator to upload an image related to the event. On the HTML page displaying the form, I am also showing a preview of the picture uploaded (HTML img tag).
我正在为两个公益网站编写和使用一个非常简单的基于 CGI (Perl) 的内容管理工具。它为网站管理员提供事件的 HTML 表单,他们可以在其中填写字段(日期、地点、标题、描述、链接等)并保存。在该表单上,我允许管理员上传与事件相关的图像。在显示表单的 HTML 页面上,我还显示了上传图片的预览(HTML img 标签)。
The Problem
问题
The problem happens when the administrator wants to change the picture. He would just have to hit the "browse" button, pick a new picture and press ok. And this works fine.
当管理员想要更改图片时会出现问题。他只需要点击“浏览”按钮,选择一张新图片,然后按“确定”即可。这工作正常。
Once the image is uploaded, my back-end CGI handles the upload and reloads the form properly.
上传图像后,我的后端 CGI 处理上传并正确重新加载表单。
The problem is that the image shown does notget refreshed. The old image is still shown, even though the database holds the right image. I have narrowed it down to the fact that the IMAGE IS CACHED in the web browser. If the administrator hits the RELOAD button in Firefox/Explorer/Safari, everything gets refreshed fine and the new image just appears.
问题是显示的图像没有刷新。即使数据库保存了正确的图像,旧图像仍会显示。我已将范围缩小到图像已缓存在 Web 浏览器中这一事实。如果管理员点击 Firefox/Explorer/Safari 中的 RELOAD 按钮,一切都会刷新,新图像就会出现。
My Solution - Not Working
我的解决方案 - 不工作
I am trying to control the cache by writing a HTTP Expires instruction with a date very far in the past.
我试图通过编写一个日期很远的 HTTP Expires 指令来控制缓存。
Expires: Mon, 15 Sep 2003 1:00:00 GMT
Remember that I am on the administrative side and I don't really care if the pages takes a little longer to load because they are always expired.
请记住,我在管理方面,我真的不在乎页面是否需要更长的时间来加载,因为它们总是过期的。
But, this does not work either.
但是,这也不起作用。
Notes
笔记
When uploading an image, its filename is not kept in the database. It is renamed as Image.jpg(to simply things out when using it). When replacing the existing image with a new one, the name doesn't change either. Just the content of the image file changes.
上传图像时,其文件名不会保存在数据库中。它被重命名为Image.jpg(在使用时简单地解决问题)。用新图像替换现有图像时,名称也不会更改。只是图像文件的内容发生了变化。
The webserver is provided by the hosting service/ISP. It uses Apache.
网络服务器由托管服务/ISP 提供。它使用Apache。
Question
题
Is there a way to force the web browser to NOT cache things from this page, not even images?
有没有办法强制 Web 浏览器不缓存此页面中的内容,甚至不缓存图像?
I am juggling with the option to actually "save the filename" with the database. This way, if the image is changed, the src of the IMG tag will also change. However, this requires a lot of changes throughout the site and I rather not do it if I have a better solution. Also, this will still not work if the new image uploaded has the same name (say the image is photoshopped a bit and re-uploaded).
我正在处理使用数据库实际“保存文件名”的选项。这样,如果图像发生变化,IMG 标签的 src 也会发生变化。但是,这需要在整个站点中进行大量更改,如果我有更好的解决方案,我宁愿不这样做。此外,如果上传的新图像具有相同的名称,这仍然不起作用(假设图像经过了一些Photoshop处理并重新上传)。
回答by epochwolf
Armin Ronacher has the correct idea. The problem is random strings can collide. I would use:
Armin Ronacher 的想法是正确的。问题是随机字符串可能会发生冲突。我会用:
<img src="picture.jpg?1222259157.415" alt="">
Where "1222259157.415" is the current time on the server.
Generate time by Javascript with performance.now()
or by Python with time.time()
其中“1222259157.415”是服务器上的当前时间。
使用 Javascriptperformance.now()
或 Python生成时间time.time()
回答by Armin Ronacher
Simple fix: Attach a random query string to the image:
简单修复:将随机查询字符串附加到图像:
<img src="foo.cgi?random=323527528432525.24234" alt="">
What the HTTP RFC says:
HTTP RFC 说的是:
Cache-Control: no-cache
But that doesn't work that well :)
但这并没有那么好:)
回答by Rick
I use PHP's file modified time function, for example:
我使用PHP的文件修改时间函数,例如:
echo <img src='Images/image.png?" . filemtime('Images/image.png') . "' />";
If you change the image then the new image is used rather than the cached one, due to having a different modified timestamp.
如果您更改图像,则使用新图像而不是缓存的图像,因为修改的时间戳不同。
回答by x-yuri
I would use:
我会用:
<img src="picture.jpg?20130910043254">
where "20130910043254" is the modification time of the file.
其中“20130910043254”是文件的修改时间。
When uploading an image, its filename is not kept in the database. It is renamed as Image.jpg (to simply things out when using it). When replacing the existing image with a new one, the name doesn't change either. Just the content of the image file changes.
上传图像时,其文件名不会保存在数据库中。它被重命名为 Image.jpg(在使用时简单地解决问题)。用新图像替换现有图像时,名称也不会更改。只是图像文件的内容发生了变化。
I think there are two types of simple solutions: 1) those which come to mind first (straightforward solutions, because they are easy to come up with), 2) those which you end up with after thinking things over (because they are easy to use). Apparently, you won't always benefit if you chose to think things over. But the second options is rather underestimated, I believe. Just think why php
is so popular ;)
我认为有两种简单的解决方案:1)首先想到的那些(直截了当的解决方案,因为它们很容易想出),2)经过深思熟虑后得出的那些(因为它们很容易用)。显然,如果您选择三思而后行,您将不会总是受益。但我相信,第二种选择被低估了。想想为什么php
这么受欢迎;)
回答by Aref Rostamkhani
use Class="NO-CACHE"
使用Class="NO-CACHE"
sample html:
示例 html:
<div>
<img class="NO-CACHE" src="images/img1.jpg" />
<img class="NO-CACHE" src="images/imgLogo.jpg" />
</div>
jQuery:
jQuery:
$(document).ready(function ()
{
$('.NO-CACHE').attr('src',function () { return $(this).attr('src') + "?a=" + Math.random() });
});
javascript:
javascript:
var nods = document.getElementsByClassName('NO-CACHE');
for (var i = 0; i < nods.length; i++)
{
nods[i].attributes['src'].value += "?a=" + Math.random();
}
Result: src="images/img1.jpg" =>src="images/img1.jpg?a=0.08749723793963926"
结果:src="images/img1.jpg" =>src="images/img1.jpg?a=0.08749723793963926"
回答by Aref Rostamkhani
You may write a proxy script for serving images - that's a bit more of work though. Something likes this:
您可以编写一个用于提供图像的代理脚本——不过这需要做更多的工作。有点像这样:
HTML:
HTML:
<img src="image.php?img=imageFile.jpg&some-random-number-262376" />
Script:
脚本:
// PHP
if( isset( $_GET['img'] ) && is_file( IMG_PATH . $_GET['img'] ) ) {
// read contents
$f = open( IMG_PATH . $_GET['img'] );
$img = $f.read();
$f.close();
// no-cache headers - complete set
// these copied from [php.net/header][1], tested myself - works
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Some time in the past
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
// image related headers
header('Accept-Ranges: bytes');
header('Content-Length: '.strlen( $img )); // How many bytes we're going to send
header('Content-Type: image/jpeg'); // or image/png etc
// actual image
echo $img;
exit();
}
Actually either no-cache headers or random number at image src should be sufficient, but since we want to be bullet proof..
实际上,图像 src 中的无缓存标头或随机数应该就足够了,但是因为我们想要防弹..
回答by Timmy T.
I'm a NEW Coder, but here's what I came up with, to stop the Browser from caching and holding onto my webcam views:
我是一个新的编码员,但这是我想出的,以阻止浏览器缓存并保留我的网络摄像头视图:
<meta Http-Equiv="Cache" content="no-cache">
<meta Http-Equiv="Pragma-Control" content="no-cache">
<meta Http-Equiv="Cache-directive" Content="no-cache">
<meta Http-Equiv="Pragma-directive" Content="no-cache">
<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">
Not sure what works on what Browser, but it does work for some: IE: Works when webpage is refreshed and when website is revisited (without a refresh). CHROME: Works only when webpage is refreshed (even after a revisit). SAFARI and iPad: Doesn't work, I have to clear the History & Web Data.
不确定什么在什么浏览器上有效,但它对某些人有效:IE:在刷新网页和重新访问网站时(不刷新)有效。CHROME:仅在刷新网页时有效(即使在重新访问后)。SAFARI 和 iPad:不起作用,我必须清除历史记录和网络数据。
Any Ideas on SAFARI/ iPad?
关于 SAFARI/iPad 的任何想法?
回答by Tarik
I checked all the answers around the web and the best one seemed to be: (actually it isn't)
我检查了网络上的所有答案,最好的答案似乎是:(实际上不是)
<img src="image.png?cache=none">
at first.
首先。
However, if you add cache=noneparameter (which is static "none" word), it doesn't effect anything, browser still loads from cache.
但是,如果您添加cache=none参数(这是静态的“无”字),则不会产生任何影响,浏览器仍会从缓存中加载。
Solution to this problem was:
这个问题的解决方法是:
<img src="image.png?nocache=<?php echo time(); ?>">
where you basically add unix timestamp to make the parameter dynamic and no cache, it worked.
您基本上添加了 unix 时间戳以使参数动态且没有缓存,它起作用了。
However, my problem was a little different: I was loading on the fly generated php chart image, and controlling the page with $_GET parameters. I wanted the image to be read from cache when the URL GET parameter stays the same, and do not cache when the GET parameters change.
但是,我的问题有点不同:我正在加载动态生成的 php 图表图像,并使用 $_GET 参数控制页面。我希望在 URL GET 参数保持不变时从缓存中读取图像,并且在 GET 参数更改时不缓存。
To solve this problem, I needed to hash $_GET but since it is array here is the solution:
为了解决这个问题,我需要散列 $_GET 但因为它是数组,所以这里是解决方案:
$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";
Edit:
编辑:
Although the above solution works just fine, sometimes you want to serve the cached version UNTIL the file is changed. (with the above solution, it disables the cache for that image completely) So, to serve cached image from browser UNTIL there is a change in the image file use:
尽管上述解决方案工作正常,但有时您希望在文件更改之前提供缓存版本。(使用上述解决方案,它会完全禁用该图像的缓存)因此,要从浏览器提供缓存图像,直到图像文件使用发生变化:
echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";
filemtime() gets file modification time.
filemtime() 获取文件修改时间。
回答by AmbroseChapel
When uploading an image, its filename is not kept in the database. It is renamed as Image.jpg (to simply things out when using it).
上传图像时,其文件名不会保存在数据库中。它被重命名为 Image.jpg(在使用时简单地解决问题)。
Change this, and you've fixed your problem. I use timestamps, as with the solutions proposed above: Image-<timestamp>.jpg
改变这一点,你就解决了你的问题。我使用时间戳,就像上面提出的解决方案一样:Image-<timestamp>.jpg
Presumably, whatever problems you're avoiding by keeping the same filename for the image can be overcome, but you don't say what they are.
据推测,通过为图像保留相同的文件名而避免的任何问题都可以克服,但您没有说明它们是什么。
回答by Doin
Your problem is that despite the Expires:
header, your browser is re-using its in-memory copy of the image from before it was updated, rather than even checking its cache.
您的问题是,尽管有Expires:
标题,您的浏览器仍在重新使用其更新之前的图像内存副本,而不是检查其缓存。
I had a very similar situation uploading product images in the admin backend for a store-like site, and in my case I decided the best option was to use javascript to force an image refresh, without using any of the URL-modifying techniques other people have already mentioned here. Instead, I put the image URL into a hidden IFRAME, called location.reload(true)
on the IFRAME's window, and then replaced my image on the page. This forces a refresh of the image, not just on the page I'm on, but also on any later pages I visit - without either client or server having to remember any URL querystring or fragment identifier parameters.
我在管理后端为类似商店的网站上传产品图片时遇到了非常相似的情况,就我而言,我决定最好的选择是使用 javascript 强制刷新图片,而不使用其他人的任何 URL 修改技术这里已经提到了。相反,我将图像 URL 放入隐藏的 IFRAME,location.reload(true)
在 IFRAME 的窗口上调用,然后在页面上替换我的图像。这会强制刷新图像,不仅在我所在的页面上,而且在我访问的任何后续页面上都如此——客户端或服务器都不必记住任何 URL 查询字符串或片段标识符参数。
I posted some code to do this in my answer here.
我在此处的回答中发布了一些代码来执行此操作。