Frage an javascript, image, refresh, url – Aktualisieren Sie das Bild mit einem neuen Bild unter derselben URL

285

Ich greife auf einen Link auf meiner Website zu, der bei jedem Zugriff ein neues Bild bereitstellt.

Wenn ich versuche, das Bild im Hintergrund zu laden und dann das Bild auf der Seite zu aktualisieren, ändert sich das Bild nicht - obwohl es aktualisiert wird, wenn ich die Seite neu lade.

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

Kopfzeilen, wie FireFox sie sieht:

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

Ich muss eine Aktualisierung nur dieses Bildes auf der Seite erzwingen. Irgendwelche Ideen?

Deine Antwort

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

0

esser sein.

<!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>
1

?var=xx zum bild 2) sollte es domänenübergreifend funktionieren

Mir gefällt die Option 4 in sehr gutdiese Antwort mit einem aber:

Es hat Probleme, zuverlässig mit Crossdomain zu arbeiten (und es muss der Servercode berührt werden).

Mein schneller und schmutziger Weg ist:

Erstellen Sie einen versteckten IframeLaden Sie die aktuelle Seite darauf (ja die ganze Seite)iframe.contentWindow.location.reload(true);Stellen Sie die Bildquelle auf sich selbst zurück

Hier ist es

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

Ja, ich weiß, setTimeout ... Du musst das in richtige Onload-Ereignisse ändern.

0

s # 4 Code und vereinfacht diesen Code ein gutes Stückdocument.write anstattsrcin demiframe CORS zu unterstützen. Konzentriert sich auch nur darauf, den Browser-Cache zu brechen und nicht jedes Bild auf der Seite neu zu laden.

Unten steht geschrieben intypescript und nutzt dieangular $ q Versprechen Bibliothek, nur zu Ihrer Information, aber sollte einfach genug sein, um Vanille Javascript zu portieren. Methode soll innerhalb einer Typoskript-Klasse leben.

Gibt ein Versprechen zurück, das aufgelöst wird, wenn das Neuladen des Iframes abgeschlossen ist. Nicht stark getestet, funktioniert aber gut für uns.

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

einige get-Abfrageparameter, wie sie vorgeschlagen wurden, hacker hinzuzufügen.

Eine bessere Antwort ist, ein paar zusätzliche Optionen in Ihrem HTTP-Header auszugeben.

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

Wenn Sie ein Datum in der Vergangenheit angeben, wird es vom Browser nicht zwischengespeichert.Cache-Control wurde in HTTP / 1.1 hinzugefügt, und das Tag "must-revalidate" gibt an, dass Proxys auch unter mildernden Umständen niemals ein altes Image bereitstellen solltenPragma: no-cache ist für aktuelle moderne Browser / Caches nicht unbedingt erforderlich, kann aber bei einigen kaputten alten Implementierungen hilfreich sein.

Mir ist gerade aufgefallen, dass Sie immer wieder das gleiche img-Tag aktualisieren. Der Browser erkennt wahrscheinlich, wenn Sie den Quellcode einstellen, dass sich der Quellcode nicht geändert hat, und es ist daher nicht störend, ihn zu aktualisieren. (Da diese Prüfung auf DOM-Ebene stattfindet und nichts mit dem Ziel zu tun hat). Was passiert, wenn Sie "?" + Nummer - zur URL des Bildes, das abgerufen wird? Edward KMETT
Das klang, als hätte es funktioniert, aber es zeigt immer noch das gleiche Bild, auch mit den Hacks. Ich werde die Header-Informationen zur Frage hinzufügen. QueueHammer
2

zeichnis der Quelle zuordnen, die ich aktualisieren wollte. Ich ließ dann von meinem Timer eine Nummer an das Ende des Namens anhängen, damit das DOM es als neues Bild ansieht und es lädt.

Z.B.

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

fordert denselben Bilderzeugungscode an, sieht jedoch für den Browser wie ein anderes Bild aus.

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);
}
Dies hätte dasselbe Problem beim Zwischenspeichern mehrerer Kopien des Images wie die Querystring-Lösung (Paolo und einige andere) und erfordert Serveränderungen. TomG
1

eine wertlose Abfragezeichenfolge zu verwenden, um eine eindeutige URL zu erstellen:

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);
}
Fügte den WQS zum Code hinzu und verifizierte, dass die Anforderung akzeptiert wird und dass der Browser die Antwort als von der Adresse + WQS stammend ansieht, ohne dass das Bild aktualisiert wird. QueueHammer
0

indem ich die Daten über ein Servlet zurückgesendet habe.

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

Dann geben Sie der Seite einfach das Servlet mit einigen Parametern, um die richtige Image-Datei zu erhalten.

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

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

Dadurch wird der aktuelle Zeitstempel automatisch angehängt, wenn Sie das Bild erstellen, und der Browser sucht erneut nach dem Bild, anstatt das Bild im Cache abzurufen.

Es gibtDate.now() dafür vp_arth
Auch wenn Sie dasselbe Bild an einer anderen Stelle erneut anzeigen, ohne den "Cache-Breaker" später, wird immer noch die alte zwischengespeicherte Version (zumindest in Firefox) angezeigt. und # :( T4NK3R
Ist dies in Ordnung, um auf Amazon S3 verwendet zu werden? Bruno Peres
Keine sehr gute Lösung, da die Caches (lokal und vorgelagert) überflutet werden.Aya Antwort hat eine bessere Art, damit umzugehen. Tgr
3

{
   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')" />

Veränderungpath='../showImage.php'; zupath='../showImage.php?'; BOOMik
Das glaube ich nicht../showImage.phpFri May 01 2015 17:34:18 GMT+0200 (Mitteleuropäische Sommerzeit) ist ein gültiger Dateiname ... Zumindest versucht es dies zu laden ... ByteHamster
Bitte erklären Sie dem OP, wie und warum dies hilft, anstatt nur Code einzufügen nomistic
1

um ein Bild zu aktualisieren, wenn auf eine Schaltfläche geklickt wird.

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')" />
-2

Zuerst binde ich das Bild mit einer falschen (Puffer-) URL und dann mit der gültigen URL.

imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + "Buffer.jpg";

imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + ".jpg";

Auf diese Weise zwinge ich den Browser, mit einer gültigen URL zu aktualisieren.

174

Als Alternative zu ...

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

...Es scheint, dass...

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

... ist ausreichend, um den Browser-Cache zu täuschen, ohne die Upstream-Caches zu umgehen, vorausgesetzt, Sie haben den richtigen zurückgegebenCache-Control Überschriften. Obwohl Sie verwenden können ...

Cache-Control: no-cache, must-revalidate

... verlieren Sie die Vorteile derIf-Modified-Since oderIf-None-Match Header, also so etwas wie ...

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

... sollte verhindern, dass der Browser das gesamte Bild erneut herunterlädt, wenn es sich nicht tatsächlich geändert hat. Getestet und funktioniert mit IE, Firefox und Chrome. Ärgerlicherweise schlägt es auf Safari fehl, es sei denn, Sie verwenden ...

Cache-Control: no-store

... obwohl dies dem Füllen von Upstream-Caches mit Hunderten identischer Images vorzuziehen sein kann, insbesondere wenn diese auf Ihrem eigenen Server ausgeführt werden. ;-)

Aktualisieren (28.09.2014): Heutzutage sieht es so ausCache-Control: no-store wird auch für Chrome benötigt.

Das funktioniert bei mir nicht. Das einzige, was in meinem Fall anders ist, ist, dass ich eine URL zu einer Controller-Aktion habe, die img von db abruft. Ich hatte andere Argumente für die Controller-Aktion und fügte sie als "...... & convert = true & t =" + new Date (). GetTime (); und "...... & convert = true #" + new Date (). getTime () ;. Was mache ich falsch? shaffooo
Es gibtZWEI Hierbei handelt es sich um Caches: Es gibt den regulären HTTP-Cache des Browsers und einen speicherinternen Cache mit Bildern, die kürzlich angezeigt wurden. Dieser letztere speicherinterne Cache wird durch den vollständigen Cache indiziertsrc Das Hinzufügen einer eindeutigen Fragmentkennung stellt sicher, dass das Bild nicht einfach aus dem Speicher abgerufen wird. Fragment-IDs werden jedoch nicht als Teil von HTTP-Anforderungen gesendet, sodass der reguläre HTTP-Cache wie gewohnt verwendet wird. Deshalb funktioniert diese Technik. Doin
Es gibt mehrere Header-Cache. Eigentlich kann ich nicht sehr gut Englisch. Kannst du mir bitte sagen, ob ich welches verwenden soll ?! Ich möchte etwas, das nicht nur das Foto zwischenspeichert, das geändert wurde (wie ein Captcha), und andere Dinge zwischenspeichert. soCache-Control: max-age=0, must-revalidate ist gut für mich? Shafizadeh
Um den Aufwand für die Objekterstellung und / oder den Methodenaufruf zu vermeiden, können Sie eine inkrementierende Ganzzahl als Cache-Buster verwenden:newImage.src = "http://localhost/image.jpg#" + i++; laindir
Großartig! Nachdem ich viel Zeit damit verbracht habe, meine verzögert geladenen Webbilder zu laden, habe ich es soeben durch Anwenden Ihrer Lösung gelöst (mit '#' funktioniert die Verwendung von '?' Bei mir nicht). Danke vielmals!!! user304602
188

um dies zu erreichen. Deshalb dachte ich, ich würde sie hier zusammenfassen (und eine vierte Methode meiner eigenen Erfindung hinzufügen):

(1) Fügen Sie der URL einen eindeutigen Cache-Busting-Abfrageparameter hinzu, z.
newImage.src = "image.jpg?t=" + new Date().getTime();

Vorteile: 100% zuverlässig, schnell und einfach zu verstehen und umzusetzen.

Nachteile: Umgeht das Zwischenspeichern insgesamt und bedeutet unnötige Verzögerungen und Bandbreitennutzung bei jedem Bildnicht zwischen den Ansichten wechseln. Füllt möglicherweise den Browser-Cache (und alle Zwischen-Caches) mit vielen, vielen Kopien des gleichen Bildes! Erfordert auch das Ändern der Bild-URL.

Wann zu verwenden: Verwenden Sie diese Option, wenn sich das Bild ständig ändert, z. B. für einen Live-Webcam-Feed. Wenn Sie diese Methode verwenden,Stellen Sie sicher, dass Sie die Bilder selbst bedienenCache-control: no-cache HTTP-Header !!! (Dies kann häufig mithilfe einer .htaccess-Datei eingerichtet werden.) Andernfalls füllen Sie die Caches nach und nach mit alten Versionen des Bildes!

(2) Fügen Sie der URL einen Abfrageparameter hinzu, der sich nur ändert, wenn die Datei dies tut, z.
echo '<img src="image.jpg?m=' . filemtime('image.jpg') . '">';

(Das ist serverseitiger PHP-Code, aber der wichtige Punkt hier ist nur, dass a? M =[letzte Änderung der Datei] Querystring wird an den Dateinamen angehängt).

Vorteile: 100% zuverlässig, schnell und einfach zu verstehen und zu implementieren,und Erhält die Caching-Vorteile perfekt.

Nachteile: Erfordert das Ändern der Bild-URL. Auch ein bisschen mehr Arbeit für den Server - er muss Zugriff auf die Datei bekommen, die zuletzt geändert wurde. Erfordert außerdem serverseitige Informationen und ist daher nicht für eine rein clientseitige Lösung zum Überprüfen eines aktualisierten Abbilds geeignet.

Wann zu verwenden: Wenn Sie Bilder zwischenspeichern möchten, diese aber möglicherweise am Serverende von Zeit zu Zeit aktualisieren müssen, ohne den Dateinamen selbst zu ändern. UND wenn Sie auf einfache Weise sicherstellen können, dass jeder Bildinstanz in Ihrem HTML-Code der richtige Querystring hinzugefügt wird.

(3) Servieren Sie Ihre Bilder mit dem HeaderCache-control: max-age=0, must-revalidate, und fügen Sie eine eindeutigememcacheFragment-ID für die URL, z. B .:
newImage.src = "image.jpg#" + new Date().getTime();

Die Idee dabei ist, dass der Cache-Control-Header Bilder in den Browser-Cache stellt, diese jedoch sofort als veraltet markiert, sodass der Browser bei jeder erneuten Anzeige beim Server nachfragen muss, ob sie sich geändert haben. Dies stellt sicher, dass der BrowserHTTP-Cache Gibt immer die neueste Kopie des Bildes zurück. Browser verwenden jedoch häufig eine speicherinterne Kopie eines Bildes, falls vorhanden, und überprüfen in diesem Fall nicht einmal ihren HTTP-Cache. Um dies zu verhindern, wird eine Fragmentkennung verwendet: Vergleich des speicherinternen AbbildssrcEnthält die Fragmentkennung, wird jedoch entfernt, bevor der HTTP-Cache abgefragt wird. (So ​​kann z.B.image.jpg#A undimage.jpg#B Möglicherweise werden beide von derimage.jpg Eintrag im HTTP-Cache des Browsers, aberimage.jpg#B würde niemals mit im Speicher gespeicherten Bilddaten von wann angezeigt werdenimage.jpg#A wurde zuletzt angezeigt).

Vorteile: Verwendet die HTTP-Caching-Mechanismen ordnungsgemäß und verwendet zwischengespeicherte Bilder, wenn sie nicht geändert wurden. Funktioniert für Server, die an einer Abfragezeichenfolge ersticken, die zu einer statischen Image-URL hinzugefügt wurde (da Server keine Fragment-IDs sehen - sie sind nur für den eigenen Gebrauch des Browsers bestimmt).

Nachteile: Beruht auf etwas zweifelhaftem (oder zumindest schlecht dokumentiertem) Verhalten von Browsern in Bezug auf Bilder mit Fragment-IDs in ihren URLs (dies habe ich jedoch erfolgreich in FF27, Chrome33 und IE11 getestet). Sendet weiterhin für jede Bildansicht eine Verlängerungsanforderung an den Server. Dies ist möglicherweise zu viel, wenn sich die Bilder nur selten ändern und / oder die Latenz ein großes Problem darstellt (da Sie auf die Verlängerungsantwort warten müssen, auch wenn das zwischengespeicherte Bild noch in Ordnung ist). . Erfordert das Ändern von Bild-URLs.

Wann zu verwenden: Verwenden Sie diese Option, wenn sich Bilder häufig ändern oder vom Client zeitweise aktualisiert werden müssen, ohne dass ein serverseitiges Skript erforderlich ist, der Vorteil des Zwischenspeicherns jedoch weiterhin besteht. Beispiel: Abfrage einer Live-Webcam, bei der ein Bild alle paar Minuten unregelmäßig aktualisiert wird. Alternativ können Sie anstelle von (1) oder (2) verwenden, wenn Ihr Server keine Abfragezeichenfolgen für statische Bild-URLs zulässt.

(4) Aktualisieren Sie ein bestimmtes Bild mit Javascript, indem Sie es zuerst in ein ausgeblendetes laden<iframe> und dann anrufenlocation.reload(true) auf dem iframecontentWindow.

Die Schritte sind:

Laden Sie das zu aktualisierende Bild in einen ausgeblendeten Iframe. Dies ist nur ein Einrichtungsschritt - es kann, falls gewünscht, lange im Voraus die eigentliche Aktualisierung durchgeführt werden. Es spielt keine Rolle, ob das Image zu diesem Zeitpunkt nicht geladen werden kann!

Sobald dies erledigt ist, löschen Sie alle Kopien dieses Bildes auf Ihrer Seite (n) oder an einer beliebigen Stelle in einem beliebigen DOM-Knoten (auch außerhalb der Seite, die in Javascript-Variablen gespeichert sind). Dies ist erforderlich, da der Browser andernfalls möglicherweise das Bild einer veralteten Kopie im Speicher anzeigt (dies gilt insbesondere für IE11): Sie müssen alle sicherstellenin Erinnerung Kopien werden gelöscht, bevor der HTTP-Cache aktualisiert wird. Wenn anderer Javascript-Code asynchron ausgeführt wird, müssen Sie möglicherweise auch verhindern, dass dieser Code in der Zwischenzeit neue Kopien des zu aktualisierenden Bildes erstellt.

Anrufiframe.contentWindow.location.reload(true). Dastrue erzwingt eine Cache-Umgehung, lädt direkt vom Server neu und überschreibt die vorhandene zwischengespeicherte Kopie.

Sobald es fertig istRe-Laden, stellen Sie die ausgeblendeten Bilder wieder her. Sie sollten jetzt die aktuelle Version vom Server anzeigen!

Bei Images mit derselben Domain können Sie das Image direkt in den Iframe laden. Für domänenübergreifende Bilder müssen Sie stattdessen eine HTML-Seite ladenvon Ihrer Domain das enthält das Bild in einem<img> Tag, andernfalls wird beim Versuch, anzurufen, die Fehlermeldung "Zugriff verweigert" angezeigtiframe.contentWindow.reload(...).

Vorteile: Funktioniert genauso wie die image.reload () -FunktionWunsch der dom hatte! Ermöglicht das normale Zwischenspeichern von Bildern (auch mit Ablaufdaten in der Zukunft, wenn Sie dies wünschen, um häufige erneute Überprüfungen zu vermeiden). Ermöglicht das Aktualisieren eines bestimmten Bildes, ohne die URLs für dieses Bild auf der aktuellen Seite oder auf anderen Seiten zu ändern, wobei nur clientseitiger Code verwendet wird.

Nachteile: Verlässt sich auf Javascript. Es wird nicht 100% ig garantiert, dass es in jedem Browser einwandfrei funktioniert (ich habe dies jedoch erfolgreich in FF27, Chrome33 und IE11 getestet). Sehr kompliziert im Vergleich zu den anderen Methoden.

Wann zu verwenden: Wenn Sie über eine Sammlung von statischen Bildern verfügen, die zwischengespeichert werden sollen, diese jedoch gelegentlich aktualisiert werden müssen, und umgehend eine visuelle Rückmeldung erhalten möchten, dass die Aktualisierung stattgefunden hat. (Insbesondere, wenn nur das Aktualisieren der gesamten Browser-Seite nicht funktioniert, wie zum Beispiel in einigen auf AJAX basierenden Web-Apps). Und wenn die Methoden (1) - (3) nicht durchführbar sind, weil Sie (aus welchen Gründen auch immer) nicht alle URLs ändern können, die möglicherweise das zu aktualisierende Bild anzeigen. (Beachten Sie, dass mit diesen 3 Methoden das Bild aktualisiert wird, aber wennEin weiterer Seite versucht dann, das Bild anzuzeigenohne die entsprechende Abfragezeichenfolge oder Fragmentkennung, möglicherweise wird stattdessen eine ältere Version angezeigt).

Die Details der Implementierung auf eine ziemlich robuste und flexible Art und Weise sind unten angegeben:

Angenommen, Ihre Website enthält ein leeres 1x1-Pixel-GIF im URL-Pfad/img/1x1blank.gif, und hat auch das folgende einzeilige PHP-Skript (nur erforderlich, um die erzwungene Aktualisierung anzuwenden)domänenübergreifend Bilder und können natürlich in jeder serverseitigen Skriptsprache unter dem URL-Pfad umgeschrieben werden/echoimg.php:

<img src="<?=htmlspecialchars(@$_GET['src'],ENT_COMPAT|ENT_HTML5,'UTF-8')?>">

Dann ist hier eine realistische Implementierung, wie Sie dies alles in Javascript tun können. Es sieht ein bisschen kompliziert aus, aber es gibt viele Kommentare, und die wichtige Funktion ist nur forceImgReload () - die ersten beiden sind leere und nicht leere Bilder. Sie sollten so gestaltet sein, dass sie effizient mit Ihrem eigenen HTML-Code arbeiten funktioniert am besten für Sie; Viele der darin enthaltenen Komplikationen können für Ihre Website unnötig sein:

// This function should blank all images that have a matching src, by changing their src property to /img/1x1blank.gif.
// ##### You should code the actual contents of this function according to your page design, and what images there are on them!!! #####
// Optionally it may return an array (or other collection or data structure) of those images affected.
// This can be used by imgReloadRestore() to restore them later, if that's an efficient way of doing it (otherwise, you don't need to return anything).
// NOTE that the src argument here is just passed on from forceImgReload(), and MAY be a relative URI;
// However, be aware that if you're reading the src property of an <img> DOM object, you'll always get back a fully-qualified URI,
// even if the src attribute was a relative one in the original HTML.  So watch out if trying to compare the two!
// NOTE that if your page design makes it more efficient to obtain (say) an image id or list of ids (of identical images) *first*, and only then get the image src,
// you can pass this id or list data to forceImgReload() along with (or instead of) a src argument: just add an extra or replacement parameter for this information to
// this function, to imgReloadRestore(), to forceImgReload(), and to the anonymous function returned by forceImgReload() (and make it overwrite the earlier parameter variable from forceImgReload() if truthy), as appropriate.
function imgReloadBlank(src)
{
  // ##### Everything here is provisional on the way the pages are designed, and what images they contain; what follows is for example purposes only!
  // ##### For really simple pages containing just a single image that's always the one being refreshed, this function could be as simple as just the one line:
  // ##### document.getElementById("myImage").src = "/img/1x1blank.gif";

  var blankList = [],
      fullSrc = /* Fully qualified (absolute) src - i.e. prepend protocol, server/domain, and path if not present in src */,
      imgs, img, i;

  for each (/* window accessible from this one, i.e. this window, and child frames/iframes, the parent window, anything opened via window.open(), and anything recursively reachable from there */)
  {
    // get list of matching images:
    imgs = theWindow.document.body.getElementsByTagName("img");
    for (i = imgs.length; i--;) if ((img = imgs[i]).src===fullSrc)  // could instead use body.querySelectorAll(), to check both tag name and src attribute, which would probably be more efficient, where supported
    {
      img.src = "/img/1x1blank.gif";  // blank them
      blankList.push(img);            // optionally, save list of blanked images to make restoring easy later on
    }
  }

  for each (/* img DOM node held only by javascript, for example in any image-caching script */) if (img.src===fullSrc)
  {
    img.src = "/img/1x1blank.gif";   // do the same as for on-page images!
    blankList.push(img);
  }

  // ##### If necessary, do something here that tells all accessible windows not to create any *new* images with src===fullSrc, until further notice,
  // ##### (or perhaps to create them initially blank instead and add them to blankList).
  // ##### For example, you might have (say) a global object window.top.blankedSrces as a propery of your topmost window, initially set = {}.  Then you could do:
  // #####
  // #####     var bs = window.top.blankedSrces;
  // #####     if (bs.hasOwnProperty(src)) bs[src]++; else bs[src] = 1;
  // #####
  // ##### And before creating a new image using javascript, you'd first ensure that (blankedSrces.hasOwnProperty(src)) was false...
  // ##### Note that incrementing a counter here rather than just setting a flag allows for the possibility that multiple forced-reloads of the same image are underway at once, or are overlapping.

  return blankList;   // optional - only if using blankList for restoring back the blanked images!  This just gets passed in to imgReloadRestore(), it isn't used otherwise.
}




// This function restores all blanked images, that were blanked out by imgReloadBlank(src) for the matching src argument.
// ##### You should code the actual contents of this function according to your page design, and what images there are on them, as well as how/if images are dimensioned, etc!!! #####
function imgReloadRestore(src,blankList,imgDim,loadError);
{
  // ##### Everything here is provisional on the way the pages are designed, and what images they contain; what follows is for example purposes only!
  // ##### For really simple pages containing just a single image that's always the one being refreshed, this function could be as simple as just the one line:
  // ##### document.getElementById("myImage").src = src;

  // ##### if in imgReloadBlank() you did something to tell all accessible windows not to create any *new* images with src===fullSrc until further notice, retract that setting now!
  // ##### For example, if you used the global object window.top.blankedSrces as described there, then you could do:
  // #####
  // #####     var bs = window.top.blankedSrces;
  // #####     if (bs.hasOwnProperty(src)&&--bs[src]) return; else delete bs[src];  // return here means don't restore until ALL forced reloads complete.

  var i, img, width = imgDim&&imgDim[0], height = imgDim&&imgDim[1];
  if (width) width += "px";
  if (height) height += "px";

  if (loadError) {/* If you want, do something about an image that couldn't load, e.g: src = "/img/brokenImg.jpg"; or alert("Couldn't refresh image from server!"); */}

  // If you saved & returned blankList in imgReloadBlank(), you can just use this to restore:

  for (i = blankList.length; i--;)
  {
    (img = blankList[i]).src = src;
    if (width) img.style.width = width;
    if (height) img.style.height = height;
  }
}




// Force an image to be reloaded from the server, bypassing/refreshing the cache.
// due to limitations of the browser API, this actually requires TWO load attempts - an initial load into a hidden iframe, and then a call to iframe.contentWindow.location.reload(true);
// If image is from a different domain (i.e. cross-domain restrictions are in effect, you must set isCrossDomain = true, or the script will crash!
// imgDim is a 2-element array containing the image x and y dimensions, or it may be omitted or null; it can be used to set a new image size at the same time the image is updated, if applicable.
// if "twostage" is true, the first load will occur immediately, and the return value will be a function
// that takes a boolean parameter (true to proceed with the 2nd load (including the blank-and-reload procedure), false to cancel) and an optional updated imgDim.
// This allows you to do the first load early... for example during an upload (to the server) of the image you want to (then) refresh.
function forceImgReload(src, isCrossDomain, imgDim, twostage)
{
  var blankList, step = 0,                                // step: 0 - started initial load, 1 - wait before proceeding (twostage mode only), 2 - started forced reload, 3 - cancelled
      iframe = window.document.createElement("iframe"),   // Hidden iframe, in which to perform the load+reload.
      loadCallback = function(e)                          // Callback function, called after iframe load+reload completes (or fails).
      {                                                   // Will be called TWICE unless twostage-mode process is cancelled. (Once after load, once after reload).
        if (!step)  // initial load just completed.  Note that it doesn't actually matter if this load succeeded or not!
        {
          if (twostage) step = 1;  // wait for twostage-mode proceed or cancel; don't do anything else just yet
          else { step = 2; blankList = imgReloadBlank(src); iframe.contentWindow.location.reload(true); }  // initiate forced-reload
        }
        else if (step===2)   // forced re-load is done
        {
          imgReloadRestore(src,blankList,imgDim,(e||window.event).type==="error");    // last parameter checks whether loadCallback was called from the "load" or the "error" event.
          if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
        }
      }
  iframe.style.display = "none";
  window.parent.document.body.appendChild(iframe);    // NOTE: if this is done AFTER setting src, Firefox MAY fail to fire the load event!
  iframe.addEventListener("load",loadCallback,false);
  iframe.addEventListener("error",loadCallback,false);
  iframe.src = (isCrossDomain ? "/echoimg.php?src="+encodeURIComponent(src) : src);  // If src is cross-domain, script will crash unless we embed the image in a same-domain html page (using server-side script,)!!!
  return (twostage
    ? function(proceed,dim)
      {
        if (!twostage) return;
        twostage = false;
        if (proceed)
        {
          imgDim = (dim||imgDim);  // overwrite imgDim passed in to forceImgReload() - just in case you know the correct img dimensions now, but didn't when forceImgReload() was called.
          if (step===1) { step = 2; blankList = imgReloadBlank(src); iframe.contentWindow.location.reload(true); }
        }
        else
        {
          step = 3;
          if (iframe.contentWindow.stop) iframe.contentWindow.stop();
          if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
        }
      }
    : null);
}

Um eine Aktualisierung eines Bildes zu erzwingen, das sich in derselben Domain wie Ihre Seite befindet, können Sie Folgendes tun:

forceImgReload("myimage.jpg");

So aktualisieren Sie ein Bild von einer anderen Stelle (domänenübergreifend):

forceImgReload("http://someother.server.com/someimage.jpg", true);

Eine fortgeschrittenere Anwendung könnte darin bestehen, ein Image nach dem Hochladen einer neuen Version auf Ihren Server neu zu laden und gleichzeitig mit dem Hochladen die erste Phase des Ladevorgangs vorzubereiten, um die sichtbare Verzögerung beim erneuten Laden für den Benutzer zu minimieren. Wenn Sie den Upload über AJAX durchführen und der Server ein sehr einfaches JSON-Array [Erfolg, Breite, Höhe] zurückgibt, sieht Ihr Code möglicherweise folgendermaßen aus:

// fileForm is a reference to the form that has a the <input typ="file"> on it, for uploading.
// serverURL is the url at which the uploaded image will be accessible from, once uploaded.
// The response from uploadImageToServer.php is a JSON array [success, width, height]. (A boolean and two ints).
function uploadAndRefreshCache(fileForm, serverURL)
{
  var xhr = new XMLHttpRequest(),
      proceedWithImageRefresh = forceImgReload(serverURL, false, null, true);
  xhr.addEventListener("load", function(){ var arr = JSON.parse(xhr.responseText); if (!(arr&&arr[0])) { proceedWithImageRefresh(false); doSomethingOnUploadFailure(...); } else { proceedWithImageRefresh(true,[arr[1],ar[2]]); doSomethingOnUploadSuccess(...); }});
  xhr.addEventListener("error", function(){ proceedWithImageRefresh(false); doSomethingOnUploadError(...); });
  xhr.addEventListener("abort", function(){ proceedWithImageRefresh(false); doSomethingOnUploadAborted(...); });
  // add additional event listener(s) to track upload progress for graphical progress bar, etc...
  xhr.open("post","uploadImageToServer.php");
  xhr.send(new FormData(fileForm));
}

Ein letzter Hinweis: Obwohl es sich bei diesem Thema um Bilder handelt, gilt es möglicherweise auch für andere Arten von Dateien oder Ressourcen. Zum Beispiel die Verwendung veralteter Skript- oder CSS-Dateien verhindern oder sogar aktualisierte PDF-Dokumente aktualisieren (mit (4) nur, wenn das Öffnen im Browser aktiviert ist). Methode (4) erfordert in diesen Fällen möglicherweise einige Änderungen am obigen Javascript.

@Doin für Methode 2, ist es nicht besser, wenn wir es tunclearstatcache(true, 'image.jpg'); zuerst? Ich habe gelesen, dass PHP die Dateistatistiken zwischenspeichert, und ich verstehe, dass PHP die alte mtime auch dann ausgeben kann, wenn sich die tatsächliche mtime ändert.Saft. ADTC
@Doin auch für Methode 2 habe ich in Chrome getestet, und es scheint, dass, wenn Sie das hinzufügen?m= Teilweise umgeht der Browser den Cache und trifft jedes Mal auf den Server. Ich weiß nicht ob# wird dieses Problem lösen oder eigene Probleme aufwerfen. ADTC
@Emilios: ... Außerdem verstehe ich Ihren Kommentar nicht, dass Sie die ganze Seite neu laden müssen. Beide Methoden (3) und (4) können in clientseitigem Javascript implementiert werden, ohne dass etwas neu geladen werden muss, außer dem einen Bild, das Sie aktualisieren. Bei Methode (3) würde dies nur bedeuten, dass Sie Javascript verwenden, um die 'src'-Eigenschaft Ihres Bildes von (z. B.) zu ändern.image.jpg#123 zuimage.jpg#124 (oder was auch immer, solange sich das Bit nach dem '#' ändert). Können Sie klarstellen, was Sie gerade nachladen und warum? Doin
@pseudosavant: Leider merke ich das erst ~ 17 Monate später, aber es tut mir leid, dass ich Ihnen mitteilen muss, dass Ihre Änderungen an meinem Code schwer beschädigt waren. (Um fair zu sein, glaube ich auch nicht, dass der Rückrufcode, den ich ursprünglich hatte, richtig war). Ich habe jetzt Teil (4) ausführlich umgeschrieben, sowohl Erklärung als auch Code. Ihr vorheriger Code hat niemals Bilder ausgeblendet (so dass dies auf ungewöhnliche Weise fehlschlagen kann, insbesondere im Internet Explorer und wenn das Bild an mehreren Stellen angezeigt wird), aber schlimmer noch, es löschte den Iframe sofort nach dem vollständigen Neuladen, was wahrscheinlich bedeutete, dass es fehlschlug arbeite nur zeitweise oder gar nicht. Es tut uns leid! Doin
6

m DOM und ersetzen Sie es durch das neue?

Sie könnten bei jedem updateImage-Aufruf neue Bilder abrufen, diese aber nicht zur Seite hinzufügen.

Es gibt verschiedene Möglichkeiten, dies zu tun. So etwas würde funktionieren.

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

Wenn es danach noch Probleme gibt, handelt es sich wahrscheinlich um ein Caching-Problem, über das die anderen Antworten sprechen.

0
<img src='someurl.com/someimage.ext' onload='imageRefresh(this, 1000);'>

Dann unten in etwas Javascript

<script language='javascript'>
 function imageRefresh(img, timeout) {
    setTimeout(function() {
     var d = new Date;
     var http = img.src;
     if (http.indexOf("&d=") != -1) { http = http.split("&d=")[0]; } 

     img.src = http + '&d=' + d.getTime();
    }, timeout);
  }
</script>

Wenn das Bild geladen wird, muss es in 1 Sekunde neu geladen werden. Ich verwende dies auf einer Seite mit Heimsicherheitskameras unterschiedlichen Typs.

Verwandte Fragen