Ich greife auf einen Link auf meiner Website zu, der bei jedem Zugriff ein neues Bild bereitstellt.
Das Problem, auf das ich stoße, ist, dass sich das Bild nicht ändert, wenn ich versuche, das Bild im Hintergrund zu laden und dann das auf der Seite zu aktualisieren - 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);
}
Header, 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?
javascript
image
url
refresh
QueueHammer
quelle
quelle
Antworten:
Versuchen Sie, am Ende der URL einen Cachebreaker hinzuzufügen:
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.
quelle
'image.jpg?' + (+new Date())
Date.now()
dafürMath.random()
Ich habe viele Variationen bei den Antworten dafür gesehen, daher dachte ich, ich würde sie hier zusammenfassen (plus eine vierte Methode meiner eigenen Erfindung hinzufügen):
(1) Fügen Sie der URL einen eindeutigen Cache-Busting-Abfrageparameter hinzu, z.
Vorteile: 100% zuverlässig, schnell und einfach zu verstehen und zu implementieren.
Nachteile: Umgeht das Caching insgesamt, was unnötige Verzögerungen und Bandbreitennutzung bedeutet, wenn sich das Bild zwischen den Ansichten nicht ändert. Füllt möglicherweise den Browser-Cache (und alle Zwischen-Caches) mit vielen, vielen Kopien genau desselben Bildes! Außerdem muss die Bild-URL geändert werden.
Verwendungszweck: 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 mit
Cache-control: no-cache
HTTP-Headern versorgen !!! (Oft kann dies mit 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.
(Das ist PHP-serverseitiger Code, aber der wichtige Punkt hier ist nur, dass ein? M = [ Dateilast der letzten Änderung] an den Dateinamen angehängt wird).
Vorteile : 100% zuverlässig, schnell und einfach zu verstehen und zu implementieren und die Caching-Vorteile perfekt zu erhalten.
Nachteile: Erfordert das Ändern der Bild-URL. Außerdem etwas mehr Arbeit für den Server - er muss Zugriff auf die zuletzt geänderte Zeit der Datei erhalten. Erfordert außerdem serverseitige Informationen und ist daher nicht für eine rein clientseitige Lösung geeignet, um nach einem aktualisierten Image zu suchen.
Verwendungszweck: Wenn Sie Bilder zwischenspeichern möchten, diese jedoch möglicherweise von Zeit zu Zeit am Serverende aktualisieren müssen, ohne den Dateinamen selbst zu ändern. UND wenn Sie leicht sicherstellen können, dass jeder Bildinstanz in Ihrem HTML-Code der richtige Querystring hinzugefügt wird.
(3) Servieren Sie Ihre Bilder mit dem Header
Cache-control: max-age=0, must-revalidate
und fügen Sie der URL eine eindeutige Memcache- Busting-Fragment-ID hinzu, z.Die Idee dabei ist, dass der Cache-Control-Header Bilder in den Browser-Cache legt, sie jedoch sofort als veraltet markiert, sodass der Browser bei jeder erneuten Anzeige beim Server nachfragen muss, ob sie geändert wurden. Dadurch wird sichergestellt, dass der HTTP-Cache des Browsers immer die neueste Kopie des Bildes zurückgibt. Browser verwenden jedoch häufig eine speicherinterne Kopie eines Bildes wieder, wenn sie eine haben, und überprüfen in diesem Fall nicht einmal ihren HTTP-Cache. Um dies zu verhindern, wird eine Fragmentkennung verwendet: Der Vergleich von In-Memory
src
-Bildern enthält die Fragmentkennung, wird jedoch entfernt, bevor der HTTP-Cache abgefragt wird. (Also zBimage.jpg#A
undimage.jpg#B
möglicherweise werden beide aus demimage.jpg
Eintrag im HTTP-Cache des Browsers angezeigt , aberimage.jpg#B
würde niemals mit speicherinternen Bilddaten von demimage.jpg#A
Zeitpunkt angezeigt werden, an dem sie zuletzt angezeigt wurden).Vorteile: Verwendet die HTTP-Caching-Mechanismen ordnungsgemäß und verwendet zwischengespeicherte Bilder, wenn sie sich nicht geändert haben. Funktioniert für Server, die an einem Querystring ersticken, der einer statischen Image-URL hinzugefügt wurde (da Server niemals Fragment-IDs sehen - sie sind nur für den eigenen Gebrauch durch den Browser bestimmt).
Nachteile: Stützt sich auf ein etwas zweifelhaftes (oder zumindest schlecht dokumentiertes) Verhalten von Browsern in Bezug auf Bilder mit Fragment-IDs in ihren URLs (ich habe dies jedoch erfolgreich in FF27, Chrome33 und IE11 getestet). Sendet weiterhin für jede Bildansicht eine Revalidierungsanforderung an den Server. Dies kann zu einem Overkill führen, wenn sich Bilder nur selten ändern und / oder die Latenz ein großes Problem darstellt (da Sie auf die Revalidierungsantwort warten müssen, auch wenn das zwischengespeicherte Image noch gut ist). . Erfordert das Ändern von Bild-URLs.
Verwendungszweck: 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, Sie jedoch den Vorteil des Caching wünschen. Zum Beispiel das Abrufen einer Live-Webcam, die alle paar Minuten ein Bild unregelmäßig aktualisiert. Verwenden Sie alternativ anstelle von (1) oder (2), wenn Ihr Server keine Abfragezeichenfolgen für statische Bild-URLs zulässt.
(4) Aktualisieren Sie ein bestimmtes Bild zwangsweise mit Javascript, indem Sie es zuerst in ein verstecktes Bild laden
<iframe>
und dannlocation.reload(true)
den Iframe aufrufencontentWindow
.Die Schritte sind:
Laden Sie das zu aktualisierende Bild in einen versteckten Iframe. Dies ist nur ein Einrichtungsschritt - auf Wunsch kann dies lange vor der eigentlichen Aktualisierung erfolgen. Es spielt nicht einmal eine Rolle, ob das Bild zu diesem Zeitpunkt nicht geladen werden kann!
Wenn dies erledigt ist, löschen Sie alle Kopien dieses Bildes auf Ihren Seiten oder irgendwo in DOM-Knoten (auch außerhalb von Seiten, die in Javascript-Variablen gespeichert sind). Dies ist erforderlich, da der Browser das Bild möglicherweise andernfalls von einer veralteten In-Memory-Kopie anzeigt (insbesondere IE11): Sie müssen sicherstellen, dass alle In-Memory- Kopien gelöscht werden, bevor Sie den HTTP-Cache aktualisieren . 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.
Rufen Sie an
iframe.contentWindow.location.reload(true)
. Dietrue
Kräfte ein Cache - Bypass, direkt vom Server neu zu laden und die bestehende cached Kopie überschreibt.Stellen Sie nach dem erneuten Laden die ausgeblendeten Bilder wieder her. Sie sollten jetzt die neue Version vom Server anzeigen!
Bei Bildern derselben Domäne können Sie das Bild direkt in den Iframe laden. Bei domänenübergreifenden Bildern müssen Sie stattdessen eine HTML-Seite aus Ihrer Domäne laden , die das Bild in einem
<img>
Tag enthält. Andernfalls wird beim Aufruf eines Anrufs der Fehler "Zugriff verweigert" angezeigtiframe.contentWindow.reload(...)
.Vorteile : Funktioniert genau wie die Funktion image.reload (), die das DOM gerne hätte! Ermöglicht das normale Zwischenspeichern von Bildern (auch mit zukünftigen Ablaufdaten, wenn Sie dies wünschen, wodurch häufige erneute Validierungen vermieden werden). 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 garantiert, dass 100% in jedem Browser ordnungsgemäß funktionieren (ich habe dies jedoch erfolgreich in FF27, Chrome33 und IE11 getestet). Sehr kompliziert im Vergleich zu den anderen Methoden.
Verwendungszweck: Wenn Sie eine Sammlung von grundsätzlich statischen Bildern haben, die Sie zwischengespeichert haben möchten, diese aber gelegentlich aktualisieren müssen und sofort visuelles Feedback erhalten, dass die Aktualisierung stattgefunden hat. (Insbesondere, wenn nur das Aktualisieren der gesamten Browserseite nicht funktioniert, wie beispielsweise bei einigen auf AJAX basierenden Webanwendungen). 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 Bild anzeigen, das Sie aktualisieren müssen. (Beachten Sie, dass mit diesen drei Methoden das Bild aktualisiert wird. Wenn jedoch eine andere Seite versucht, dieses Bild ohne den entsprechenden Querystring oder die entsprechende Fragmentkennung anzuzeigen, wird möglicherweise stattdessen eine ältere Version angezeigt.)
Die Details für eine faire und flexible Umsetzung sind nachstehend aufgeführt:
Nehmen wir an, Ihre Website enthält ein leeres GIF mit 1 x 1 Pixel im URL-Pfad
/img/1x1blank.gif
sowie das folgende einzeilige PHP-Skript (das nur zum Anwenden einer erzwungenen Aktualisierung auf domänenübergreifende Bilder erforderlich ist und in jeder serverseitigen Skriptsprache neu geschrieben werden kann natürlich) unter dem URL-Pfad/echoimg.php
:Im Folgenden finden Sie 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 forceImgReload () - die ersten beiden nur leeren und nicht leeren Bilder. Sie sollten so gestaltet sein, dass sie effizient mit Ihrem eigenen HTML-Code arbeiten. Codieren Sie sie also als funktioniert am besten für Sie; Viele der damit verbundenen Komplikationen sind für Ihre Website möglicherweise nicht erforderlich:
Um eine Aktualisierung eines Bildes zu erzwingen, das sich in derselben Domain wie Ihre Seite befindet, können Sie einfach Folgendes tun:
So aktualisieren Sie ein Bild von einem anderen Ort (domänenübergreifend):
Eine fortgeschrittenere Anwendung könnte darin bestehen, ein Bild nach dem Hochladen einer neuen Version auf Ihren Server neu zu laden und gleichzeitig mit dem Hochladen die Anfangsphase des Neuladevorgangs 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:
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. Verhindern Sie beispielsweise die Verwendung veralteter Skript- oder CSS-Dateien oder aktualisieren Sie möglicherweise sogar aktualisierte PDF-Dokumente (verwenden Sie (4) nur, wenn diese zum Öffnen im Browser eingerichtet sind). Methode (4) erfordert in diesen Fällen möglicherweise einige Änderungen am obigen Javascript.
quelle
image.jpg#123
inimage.jpg#124
(oder was auch immer ) zu ändern , solange sich das Bit nach dem '#' ändert). Können Sie klarstellen, was Sie neu laden und warum?contentWindow
über Javascript darauf zugreifen , um denreload(true)
Aufruf auszuführen , der der kritische Teil der Methode ist ... also nein, Methode (4) ) funktioniert nicht für domänenübergreifende Inhalte. Gut erkannt; Ich werde die "Nachteile" aktualisieren, um das einzuschließen.Als Alternative zu ...
...Es scheint, dass...
... reicht aus, um den Browser-Cache zu täuschen, ohne Upstream-Caches zu umgehen, vorausgesetzt, Sie haben die richtigen
Cache-Control
Header zurückgegeben. Obwohl Sie verwenden können ...... Sie verlieren die Vorteile der
If-Modified-Since
oderIf-None-Match
Header, also so etwas wie ...... sollte verhindern, dass der Browser das gesamte Bild erneut herunterlädt, wenn es sich nicht geändert hat. Getestet und funktioniert mit IE, Firefox und Chrome. Ärgerlicherweise schlägt es auf Safari fehl, es sei denn, Sie verwenden ...
... obwohl dies immer noch vorzuziehen ist, um Upstream-Caches mit Hunderten identischer Images zu füllen, insbesondere wenn sie auf Ihrem eigenen Server ausgeführt werden. ;-);
Update (28.09.2014): Heutzutage scheint es, dass
Cache-Control: no-store
es auch für Chrome benötigt wird.quelle
src
Attribut indiziert. Durch Hinzufügen einer eindeutigen Fragmentkennung wird sichergestellt, 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.Cache-Control: max-age=0, must-revalidate
ist gut für mich?newImage.src = "http://localhost/image.jpg#" + i++;
Entfernen Sie nach dem Erstellen des neuen Bildes das alte Bild aus dem DOM und ersetzen Sie es durch das neue?
Möglicherweise greifen Sie bei jedem Aufruf von updateImage nach neuen Bildern, fügen diese jedoch nicht zur Seite hinzu.
Es gibt verschiedene Möglichkeiten, dies zu tun. So etwas würde funktionieren.
Wenn das immer noch Probleme gibt, handelt es sich wahrscheinlich um ein Caching-Problem, über das in den anderen Antworten gesprochen wird.
quelle
Eine Antwort besteht darin, einige get-Abfrageparameter, wie vorgeschlagen, hackisch hinzuzufügen.
Eine bessere Antwort besteht darin, einige zusätzliche Optionen in Ihrem HTTP-Header auszugeben.
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 Must-Revalidate-Tag zeigt an, dass Proxys auch unter mildernden Umständen niemals ein altes Image bereitstellen sollten. DiesPragma: no-cache
ist für aktuelle moderne Browser / Caches nicht unbedingt erforderlich, kann aber bei einigen kaputten, kaputten alten Implementierungen hilfreich sein.quelle
Ich hatte eine Anforderung: 1) kann
?var=xx
dem Bild keine hinzufügen 2) es sollte domänenübergreifend funktionierenIch mag die Option Nr. 4 in dieser Antwort mit einer, aber:
Mein schneller und schmutziger Weg ist:
iframe.contentWindow.location.reload(true);
Hier ist es
Ja, ich weiß, setTimeout ... Sie müssen das in richtige Onload-Ereignisse ändern.
quelle
Dann unten in etwas Javascript
Wenn das Bild geladen wird, wird es in 1 Sekunde neu geladen. Ich verwende dies auf einer Seite mit Heimsicherheitskameras unterschiedlichen Typs.
quelle
Am Ende ließ ich den Server jede Anforderung für ein Image in diesem Verzeichnis der Quelle zuordnen, die ich aktualisieren wollte. Ich ließ dann meinen Timer eine Nummer an das Ende des Namens anhängen, damit das DOM es als neues Bild sehen und es laden konnte.
Z.B
fordert den gleichen Bilderzeugungscode an, sieht jedoch für den Browser wie verschiedene Bilder aus.
quelle
quelle
../showImage.phpFri May 01 2015 17:34:18 GMT+0200 (Mitteleuropäische Sommerzeit)
ein gültiger Dateiname ist ... Zumindest versucht er dies zu laden ...path='../showImage.php';
zupath='../showImage.php?';
Setze seinen eigenen src als seinen src.
quelle
Versuchen Sie es mit einem wertlosen Querystring, um daraus eine eindeutige URL zu machen:
quelle
Stark auf Doin der # 4 - Code, unter Verwendung des unter Beispiel vereinfacht , dass Code ein großes Stück
document.write
stattsrc
in deriframe
CORS zu unterstützen. Konzentriert sich auch nur darauf, den Browser-Cache zu sprengen und nicht jedes Bild auf der Seite neu zu laden.Das Folgende ist in geschrieben
typescript
und verwendet dieangular
$ q- Versprechen-Bibliothek, nur zu Ihrer Information, sollte aber einfach genug sein, um auf Vanille-Javascript zu portieren. Die Methode soll in einer Typoskriptklasse leben.Gibt ein Versprechen zurück, das aufgelöst wird, wenn der Iframe das Neuladen abgeschlossen hat. Nicht stark getestet, funktioniert aber gut für uns.
quelle
+ encodeURI(src) +
um ordnungsgemäßsrc
in der zu entkommeniframe
.Der folgende Code ist nützlich, um das Bild zu aktualisieren, wenn auf eine Schaltfläche geklickt wird.
quelle
Ich habe dieses Problem gelöst, indem ich die Daten über ein Servlet zurückgesendet habe.
Dann geben Sie auf der Seite einfach das Servlet mit einigen Parametern ein, um die richtige Bilddatei zu erhalten.
quelle
Hier ist meine Lösung. Es ist sehr einfach. Die Frame-Planung könnte besser sein.
quelle
Keine Notwendigkeit für
new Date().getTime()
Spielereien. Sie können den Browser austricksen, indem Sie ein unsichtbares Dummy-Bild haben und jQuery .load () verwenden und dann jedes Mal ein neues Bild erstellen:quelle
Einfache Lösung: Fügen Sie diesen Header zur Antwort hinzu:
Warum dies funktioniert, wird auf dieser maßgeblichen Seite klar erläutert: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
Es erklärt auch, warum
no-cache
nicht funktioniert.Andere Antworten funktionieren nicht, weil:
Caching.delete
handelt von einem neuen Cache, den Sie für die Offline-Arbeit erstellen können, siehe: https://web.dev/cache-api-quick-guide/Fragmente, die ein # in der URL verwenden, funktionieren nicht, da das # den Browser anweist, keine Anforderung an den Server zu senden.
Ein Cache-Buster mit einem zufälligen Teil, der der URL hinzugefügt wird, funktioniert, füllt aber auch den Browser-Cache. In meiner App wollte ich alle paar Sekunden ein 5-MB-Bild von einer Webcam herunterladen. Es dauert nur eine Stunde oder weniger, um Ihren PC vollständig einzufrieren. Ich weiß immer noch nicht, warum der Browser-Cache nicht auf ein vernünftiges Maximum beschränkt ist, aber das ist definitiv ein Nachteil.
quelle
Ich habe das Skript von AlexMA verbessert , um meine Webcam auf einer Webseite anzuzeigen , die regelmäßig ein neues Bild mit demselben Namen hochlädt. Ich hatte Probleme, dass das Bild manchmal aufgrund eines fehlerhaften Bildes oder eines nicht vollständig (hoch) geladenen Bildes flackerte. Um ein Flackern zu vermeiden, überprüfe ich die natürliche Höhe des Bildes, da sich die Größe meines Webcam-Bildes nicht geändert hat. Nur wenn die geladene Bildhöhe der ursprünglichen Bildhöhe entspricht, wird das vollständige Bild auf der Seite angezeigt.
quelle
Ich habe das folgende Konzept verwendet, das Bild zuerst mit einer falschen (Puffer-) URL und dann mit der gültigen URL zu binden.
Auf diese Weise zwinge ich den Browser, mit einer gültigen URL zu aktualisieren.
quelle