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

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

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

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


当前回答

我有一个要求:1)不能添加任何?var=xx的图像2)它应该跨域工作

我真的很喜欢这个答案中的第4个选项,但是:

它在可靠地跨域工作方面存在问题(并且需要修改服务器代码)。

我的捷径是:

创建隐藏iframe 加载当前页面到它(是的,整个页面) iframe.contentWindow.location.reload(真正的); 重新设置图像源为其本身

在这里

function RefreshCachedImage() {
    if (window.self !== window.top) return; //prevent recursion
    var $img = $("#MYIMAGE");
    var src = $img.attr("src");
    var iframe = document.createElement("iframe");
    iframe.style.display = "none";
    window.parent.document.body.appendChild(iframe);
    iframe.src = window.location.href;
    setTimeout(function () {
        iframe.contentWindow.location.reload(true);
        setTimeout(function () {
            $img.removeAttr("src").attr("src", src);
        }, 2000);
    }, 2000);
}

我知道,setTimeout。您必须将其更改为适当的onload-events。

其他回答

回答:你可以简单地使用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除外)。

我最终要做的是让服务器将对该目录下的图像的任何请求映射到我试图更新的源。然后,我让计时器在名称的末尾附加一个数字,这样DOM就会将其视为新图像并加载它。

E.g.

http://localhost/image.jpg
//and
http://localhost/image01.jpg

将请求相同的图像生成代码,但它将看起来像不同的图像浏览器。

var newImage = new Image();
newImage.src = "http://localhost/image.jpg";
var count = 0;
function updateImage()
{
    if(newImage.complete) {
        document.getElementById("theText").src = newImage.src;
        newImage = new Image();
        newImage.src = "http://localhost/image/id/image" + count++ + ".jpg";
    }
    setTimeout(updateImage, 1000);
}

在创建新图像之后,是否从DOM中删除旧图像并用新图像替换它?

您可以在每次updateImage调用时抓取新图像,但不将它们添加到页面。

有很多方法可以做到这一点。像这样的东西是可行的。

function updateImage()
{
    var image = document.getElementById("theText");
    if(image.complete) {
        var new_image = new Image();
        //set up the new image
        new_image.id = "theText";
        new_image.src = image.src;           
        // insert new image and remove old
        image.parentNode.insertBefore(new_image,image);
        image.parentNode.removeChild(image);
    }

    setTimeout(updateImage, 1000);
}

在得到工作后,如果仍然有问题,它可能是缓存问题,就像其他答案谈论。

作为……的替代方案。

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。

下面的代码用于在单击按钮时刷新图像。

function reloadImage(imageId) {
   imgName = 'vishnu.jpg'; //for example
   imageObject = document.getElementById(imageId);
   imageObject.src = imgName;
}

<img src='vishnu.jpg' id='myimage' />

<input type='button' onclick="reloadImage('myimage')" />