在相同的URL上刷新图像为新的图片

451

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

我的问题是,如果我尝试在后台加载图像,然后更新页面上的图像,那么图像不会更改-但当我重新加载页面时,它会更新。

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);
}

火狐浏览器看到的标头:

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

我需要强制刷新页面上的特定图片。有什么想法吗?


请参考以下链接:https://dev59.com/ZHVC5IYBdhLWcg3w-mZO - Philibert Perusse
19
十年过去了,我们仍然需要用hack的方法来实现这一点。浏览器制造商不能提供:img.reload()吗? - Daniel Wu
2
fetch是2022年更好的解决方案!请参见https://dev59.com/6XNA5IYBdhLWcg3wIqPr#66312176 - C-Y
23个回答

3

function reloadImage(imageId)
{
   path = '../showImage.php?cache='; //for example
   imageObject = document.getElementById(imageId);
   imageObject.src = path + (new Date()).getTime();
}
<img src='../showImage.php' id='myimage' />

<br/>

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


4
请解释给OP,如何以及为什么这有帮助,而不只是粘贴代码。 - nomistic
我认为 ../showImage.phpFri May 01 2015 17:34:18 GMT+0200 (Mitteleuropäische Sommerzeit) 不是一个有效的文件名... 至少它试图加载的是这样... - ByteHamster
path='../showImage.php'; 更改为 path='../showImage.php?'; - BOOMik

2
我曾经使用Unsplash的随机图片功能时遇到了同样的问题。在URL的末尾添加一个虚拟查询字符串的想法是正确的,但在这种情况下,完全随机的参数不起作用(我已经尝试过了)。我可以想象对于其他一些服务也是如此,但对于Unsplash,参数需要是sig,因此您的图片URL将是,例如http://example.net/image.jpg?sig=RANDOM,其中RANDOM是一个随机字符串,在更新时将不相同。我使用Math.random()*100,但日期也可以。

您需要执行以上操作,因为如果没有它,浏览器将看到该路径上的图像已经被加载,并将使用缓存的图像来加速加载。

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


2
document.getElementById("img-id").src = document.getElementById("img-id").src

将其自身的src设置为其源。


1

尝试使用一个无用的查询字符串来使其成为唯一的URL:

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

    setTimeout(updateImage, 1000);
}

将WQS添加到代码中,并验证请求被接受,浏览器看到响应来自地址+WQS,而图像不会刷新。 - QueueHammer

1
基于Doin的#4代码,下面的示例简化了该代码,并使用document.write而不是srciframe中支持CORS。还仅关注破坏浏览器缓存,而不是重新加载页面上的每个图像。
以下内容使用typescript编写,并使用angular$q promise库,只是提供信息,但应很容易转换为vanilla javascript。该方法旨在存在于typescript类中。
返回一个承诺,当iframe完成重新加载时将解决该承诺。未经过严格测试,但对我们有效。
    mmForceImgReload(src: string): ng.IPromise<void> {
        var deferred = $q.defer<void>();
        var iframe = window.document.createElement("iframe");

        var firstLoad = true;
        var loadCallback = (e) => {
            if (firstLoad) {
                firstLoad = false;
                iframe.contentWindow.location.reload(true);
            } else {
                if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
                deferred.resolve();
            }
        }
        iframe.style.display = "none";
        window.parent.document.body.appendChild(iframe);
        iframe.addEventListener("load", loadCallback, false);
        iframe.addEventListener("error", loadCallback, false);
        var doc = iframe.contentWindow.document;
        doc.open();
        doc.write('<html><head><title></title></head><body><img src="' + src + '"></body></html>');
        doc.close();
        return deferred.promise;
    }

为了防止 XSS 漏洞,您应该使用 + encodeURI(src) + 来正确转义 iframe 中的 src - Tino

1
将图像的第二个副本放在同一位置,然后删除原始图像。
function refreshImg(ele){
    ele.insertAdjacentHTML('beforebegin',ele.outerHTML);
    ele.parentNode.removeChild(ele);
}

这将有效地刷新图像。

同时还支持多种浏览器insertAdjacentHTMLouterHTMLparentNoderemoveChild都是跨浏览器的。

从性能上来说,在大多数情况下,性能损失可能是可以忽略不计的。@Paolo Bergantino's 的回答可能比这个函数更好。使用他的回答只会影响一个 DOM 元素,而使用这个函数会影响两个元素。

更新

在撰写本文时,这个方法效果良好。自那时以来,浏览器已重新设计了它们的浏览器缓存。我还没有测试过哪些浏览器适用,哪些不适用......


截至02/22,它似乎不再起作用了,至少在FF 96.0.3上从控制台测试无效(叹气)。即使先删除旧版本的图像再添加HTML也不行。缓存可能已经改进了。 - Giampaolo Ferradini

1
我改进了AlexMA的脚本,用于在网页上显示我的网络摄像头,并定期上传具有相同名称的新图像。有时候会出现闪烁的问题,因为图像损坏或未完全上传。为了防止闪烁,我检查了图像的自然高度,因为我的网络摄像头图像的大小没有改变。只有当已加载的图像高度与原始图像高度匹配时,才会在页面上显示完整的图像。
  <h3>Webcam</h3>
  <p align="center">
    <img id="webcam" title="Webcam" onload="updateImage();" src="https://www.your-domain.com/webcam/current.jpg" alt="webcam image" width="900" border="0" />

    <script type="text/javascript" language="JavaScript">

    // off-screen image to preload next image
    var newImage = new Image();
    newImage.src = "https://www.your-domain.com/webcam/current.jpg";

    // remember the image height to prevent showing broken images
    var height = newImage.naturalHeight;

    function updateImage()
    {
        // for sure if the first image was a broken image
        if(newImage.naturalHeight > height)
        {
          height = newImage.naturalHeight;
        }

        // off-screen image loaded and the image was not broken
        if(newImage.complete && newImage.naturalHeight == height) 
        {
          // show the preloaded image on page
          document.getElementById("webcam").src = newImage.src;
        }

        // preload next image with cachebreaker
        newImage.src = "https://www.your-domain.com/webcam/current.jpg?time=" + new Date().getTime();

        // refresh image (set the refresh interval to half of webcam refresh, 
        // in my case the webcam refreshes every 5 seconds)
        setTimeout(updateImage, 2500);
    }

    </script>
</p>

0
这是我的解决方案。它非常简单。帧调度可能会更好。
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">      
        <title>Image Refresh</title>
    </head>

    <body>

    <!-- Get the initial image. -->
    <img id="frame" src="frame.jpg">

    <script>        
        // Use an off-screen image to load the next frame.
        var img = new Image();

        // When it is loaded...
        img.addEventListener("load", function() {

            // Set the on-screen image to the same source. This should be instant because
            // it is already loaded.
            document.getElementById("frame").src = img.src;

            // Schedule loading the next frame.
            setTimeout(function() {
                img.src = "frame.jpg?" + (new Date).getTime();
            }, 1000/15); // 15 FPS (more or less)
        })

        // Start the loading process.
        img.src = "frame.jpg?" + (new Date).getTime();
    </script>
    </body>
</html>

0
以下代码可用于在单击按钮时刷新图像。
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')" />

被踩了。因为这只是@Mahmoud代码的略微修改副本,但与此相反,这里并没有刷新图像。 - Tino

0

我通过一个servlet将数据发送回来解决了这个问题。

response.setContentType("image/png");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.setDateHeader("Expires", 0);

BufferedImage img = ImageIO.read(new File(imageFileName));

ImageIO.write(img, "png", response.getOutputStream());

然后从您刚才提供的页面,将servlet与一些参数一起传递,以获取正确的图像文件。

<img src="YourServlet?imageFileName=imageNum1">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接