我正在访问我的网站上的一个链接,每次访问它都会提供一个新的图像。

我遇到的问题是,如果我试图在后台加载图像,然后更新页面上的图像,图像不会改变——尽管在我重新加载页面时它会更新。

var newImage = new Image();
newImage.src = "http://localhost/image.jpg";

function updateImage()
{
if(newImage.complete) {
    document.getElementById("theText").src = newImage.src;
    newImage = new Image();
    number++;
    newImage.src = "http://localhost/image/id/image.jpg?time=" + new Date();
}

    setTimeout(updateImage, 1000);
}

FireFox看到的头文件:

HTTP/1.x 200 OK
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: image/jpeg
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Server: Microsoft-HTTPAPI/1.0
Date: Thu, 02 Jul 2009 23:06:04 GMT

我需要强制刷新页面上的图像。什么好主意吗?


当前回答

I had this same issue using the Unsplash random image feature. The idea of adding a dummy query string to the end of the URL is correct, but in this instance a completely random parameter doesn't work (I tried it). I can imagine it's the same for some other services too, but for unsplash the parameter needs to be sig, so your image URL would be, for example, http://example.net/image.jpg?sig=RANDOM where random is a random string that will NOT be the same when you update it. I used Math.random()*100 but date is suitable too.

您需要这样做,因为如果没有它,浏览器将看到所述路径上的图像已经加载,并将使用缓存的图像来加速加载。

参见https://github.com/unsplash/unsplash-source-js/issues/9

其他回答

尝试在url的末尾添加cachebreaker:

newImage.src = "http://localhost/image.jpg?" + new Date().getTime();

这将在创建图像时自动附加当前时间戳,并且它将使浏览器重新查找图像,而不是从缓存中检索图像。

一种解决方法是像建议的那样笨拙地添加一些get查询参数。

更好的答案是在HTTP报头中发出两个额外的选项。

Pragma: no-cache
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Cache-Control: no-cache, must-revalidate

通过提供过去的日期,它不会被浏览器缓存。缓存控制是在HTTP/1.1中添加的,必须重新验证标签表明代理永远不应该提供旧的映像,即使是在可减轻的情况下,而Pragma: no-cache对于当前的现代浏览器/缓存来说并不是真正必要的,但可能有助于一些复杂的破碎的旧实现。

回答:你可以简单地使用fetch和缓存选项设置为'reload'来更新缓存:

fetch("my-image-url.jpg", {cache: 'reload', mode: 'no-cors'})

下面的函数将更新缓存并重新加载页面中的图像:

async function reloadImg(url) {
  await fetch(url, { cache: 'reload', mode: 'no-cors' })
  document.body.querySelectorAll(`img[src='${url}']`)
    .forEach(img => img.src = url)
}

它返回一个承诺,所以如果你愿意,你可以像await reloadImg("my-image-url.jpg")一样使用它。

如今,fetch API几乎在任何地方都可用(当然,IE除外)。

不需要新的Date(). gettime()恶作剧。你可以通过使用jQuery .load()创建一个不可见的虚拟图像来欺骗浏览器,然后每次创建一个新的图像:

<img src="" id="dummy", style="display:none;" />  <!-- dummy img -->
<div id="pic"></div>

<script type="text/javascript">
  var url = whatever;
  // You can repeat the following as often as you like with the same url
  $("#dummy").load(url);
  var image = new Image();
  image.src = url;
  $("#pic").html("").append(image);
</script>

作为……的替代方案。

newImage.src = "http://localhost/image.jpg?" + new Date().getTime();

...看来……

newImage.src = "http://localhost/image.jpg#" + new Date().getTime();

...足以欺骗浏览器缓存而不绕过任何上游缓存,假设您返回了正确的cache - control头。虽然你可以用…

Cache-Control: no-cache, must-revalidate

...你就失去了If-Modified-Since或If-None-Match标头的好处,所以…

Cache-Control: max-age=0, must-revalidate

...应该防止浏览器重新下载整个图像,如果它实际上没有改变。在IE, Firefox和Chrome上进行测试和工作。令人恼火的是,它在Safari上失败了,除非你使用…

Cache-Control: no-store

...尽管这可能比用数百个相同的映像填充上游缓存更可取,特别是当它们运行在您自己的服务器上时。: -)

更新(2014-09-28):现在看起来像是Cache-Control: Chrome也需要no-store。