Deaktivieren Sie den Cache für einige Bilder

113

Ich generiere einige Bilder mit einer PHP-Bibliothek.

Manchmal lädt der Browser die neu generierte Datei nicht.

Wie kann ich den Cache nur für von mir dynamisch erstellte Bilder deaktivieren?

Hinweis: Ich muss im Laufe der Zeit denselben Namen für die erstellten Bilder verwenden.

Dole Doug
quelle

Antworten:

233

Eine übliche und einfache Lösung für dieses Problem, das sich wie ein Hack anfühlt, aber ziemlich portabel ist, besteht darin, jeder Anforderung für das dynamische Image eine zufällig generierte Abfragezeichenfolge hinzuzufügen.

Also zum Beispiel -

<img src="image.png" />

Würde werden

<img src="image.png?dummy=8484744" />

Oder

<img src="image.png?dummy=371662" />

Aus Sicht des Webservers wird auf dieselbe Datei zugegriffen, aus Sicht des Browsers kann jedoch kein Caching durchgeführt werden.

Die Zufallszahlengenerierung kann entweder auf dem Server beim Bereitstellen der Seite (stellen Sie nur sicher, dass die Seite selbst nicht zwischengespeichert ist ...) oder auf dem Client (mithilfe von JavaScript) erfolgen.

Sie müssen überprüfen, ob Ihr Webserver mit diesem Trick umgehen kann.

Hexagon
quelle
87
Verwenden Sie anstelle von Zufallszahlen den Zeitstempel, den die Daten geändert haben, oder eine Versionsnummer der reflektierten Daten.
lhunath
19
Bitte beachten Sie: Sie verhindern nicht, dass der Browser das Bild zwischenspeichert, sondern nur, dass das zwischengespeicherte Bild angezeigt wird. Das Anwenden der richtigen Überschriften auf Ihr Bild ist imho der beste Weg (siehe die Lösung von lhunath unten). Da Sie auf diese Weise auch den Cache unnötig mit Bildern füllen, die Sie nicht zwischenspeichern möchten, entstehen weniger Cache-Speicherplatz für Dinge, die tatsächlich zwischengespeichert werden sollen.
Jos
Ich glaube, dieser Artikel erklärt den Grund für ein solches Verhalten.
Metalcoder
1
Dies funktioniert nicht wirklich, das Bild muss auf eine andere Weise geleert werden (normalerweise bleibt das Bild beim Zuschneiden des Bildes gleich)
Ben
44

Browser-Caching-Strategien können über HTTP-Header gesteuert werden. Denken Sie daran, dass sie wirklich nur ein Hinweis sind. Da Browser in diesem (und jedem anderen) Bereich furchtbar inkonsistent sind, benötigen Sie mehrere Header, um den gewünschten Effekt auf eine Reihe von Browsern zu erzielen.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");
lhunath
quelle
1
Dies wird auf die gesamte Seite angewendet. Ich kann den Cache nicht nur für ein Bild deaktivieren (ein bestimmtes Bild von dieser Seite).
Dole Doug
5
@Thorpe: Dies gilt für HTTP-Antworten. Was in der Antwort enthalten ist, spielt keine Rolle. Ob Bilddaten, HTML-Daten oder was auch immer. Wenn es nicht funktioniert hat, haben Sie es wahrscheinlich nicht richtig gemacht. Überprüfen Sie die HTTP-Header in Ihrer Antwort, um festzustellen, ob sie korrekt zugewiesen wurden.
lhunath
Ich wünschte, dies würde funktionieren ... Chrome hat keine Probleme, aber Firefox 14 und IE 8 lehnen es ab, die Bilder zu aktualisieren, selbst wenn die oben genannten Header gesendet werden. Dies wäre eine viel sauberere Lösung gewesen, als der Abfragezeichenfolge beliebige Parameter hinzuzufügen. Seufzer
Pawel Krakowiak
2
@PawelKrakowiak Beachten Sie, dass das Hinzufügen von Headern für bereits zwischengespeicherte Bilder nicht funktioniert , da der Browser den Server nicht einmal danach fragt und daher die Header niemals sieht. Sie funktionieren für alle Bildanforderungen, die nach dem Hinzufügen gestellt wurden.
lhunath
2
Diese Lösung ist für Programmierer gedacht, nicht für Webdesigner. Ich dachte, ich würde darauf hinweisen, weil man einem Bild nicht einfach Kopfzeilen öffnen und abbilden und hinzufügen kann, es sei denn, sie selbst erzeugen das Bild in einer Programmiersprache und dies scheint die Kommentatoren zu verwirren.
Bruce
12

Wenn Sie dies dynamisch im Browser mit Javascript tun müssen, finden Sie hier ein Beispiel ...

<img id=graph alt="" 
  src="http://www.kitco.com/images/live/gold.gif" 
  />

<script language="javascript" type="text/javascript">
    var d = new Date(); 
    document.getElementById("graph").src = 
      "http://www.kitco.com/images/live/gold.gif?ver=" + 
       d.getTime();
</script>
Anton Swanevelder
quelle
12

Lösung 1 ist nicht großartig. Es funktioniert, aber wenn Sie am Ende Ihrer Bilddateien hackige zufällige oder zeitgestempelte Abfragezeichenfolgen hinzufügen, wird der Browser jede Version jedes Bildes erneut herunterladen und zwischenspeichern, jedes Mal, wenn eine Seite geladen wird, unabhängig davon, ob sich das Bild geändert hat oder nicht auf dem Server.

Lösung 2 ist nutzlos. Das Hinzufügen von nocacheHeadern zu einer Bilddatei ist nicht nur sehr schwierig zu implementieren, sondern auch völlig unpraktisch, da Sie voraussagen müssen, wann es benötigt wird, wenn Sie zum ersten Mal ein Bild laden, von dem Sie glauben, dass es sich zu einem späteren Zeitpunkt ändern könnte .

Etags eingeben ...

Der absolut beste Weg , dies zu lösen, ist die Verwendung von ETAGS in einer .htaccess- Datei in Ihrem Bilderverzeichnis. Im Folgenden wird Apache angewiesen, einen eindeutigen Hash in den Headern der Bilddatei an den Browser zu senden. Dieser Hash ändert sich immer nur, wenn die Bilddatei geändert wird, und diese Änderung veranlasst den Browser, das Bild bei der nächsten Anforderung neu zu laden.

<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>
Cronoklee
quelle
11

Ich überprüfte alle Antworten und die beste schien zu sein (was nicht der Fall ist):

<img src="image.png?cache=none">

zunaechst.

Wenn Sie jedoch den Parameter cache = none hinzufügen (dies ist das statische Wort "none"), hat dies keine Auswirkungen. Der Browser wird weiterhin aus dem Cache geladen.

Die Lösung für dieses Problem war:

<img src="image.png?nocache=<?php echo time(); ?>">

Wo Sie im Grunde genommen einen Unix-Zeitstempel hinzufügen, um den Parameter dynamisch und ohne Cache zu machen, hat es funktioniert.

Mein Problem war jedoch etwas anders: Ich habe im laufenden Betrieb ein generiertes PHP-Diagrammbild geladen und die Seite mit $ _GET-Parametern gesteuert. Ich wollte, dass das Bild aus dem Cache gelesen wird, wenn der URL-GET-Parameter gleich bleibt, und nicht zwischengespeichert wird, wenn sich die GET-Parameter ändern.

Um dieses Problem zu lösen, musste ich $ _GET hashen, aber da es sich um ein Array handelt, ist hier die Lösung:

$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";

Bearbeiten :

Obwohl die obige Lösung einwandfrei funktioniert, möchten Sie manchmal die zwischengespeicherte Version bereitstellen, bis die Datei geändert wird. (Mit der obigen Lösung wird der Cache für dieses Bild vollständig deaktiviert.) Um zwischengespeicherte Bilder vom Browser bereitzustellen, BIS es eine Änderung in der Verwendung der Bilddatei gibt:

echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";

filemtime () erhält die Änderungszeit der Datei.

Tarik
quelle
4

Ich weiß, dass dieses Thema alt ist, aber es rangiert bei Google sehr gut. Ich habe herausgefunden, dass das Einfügen in Ihren Header gut funktioniert.

<meta Http-Equiv="Cache-Control" Content="no-cache">
<meta Http-Equiv="Pragma" Content="no-cache">
<meta Http-Equiv="Expires" Content="0">
<meta Http-Equiv="Pragma-directive: no-cache">
<meta Http-Equiv="Cache-directive: no-cache">
Dimitri Visser
quelle
Moderne Browser ignorieren diese Anweisungen leider, daher funktioniert diese Lösung möglicherweise nur in einigen Browsern. Außerdem wird der Cache für alles deaktiviert, nicht nur für bestimmte Bilder
ZioCain
4

Ich habe nur nach einer Lösung dafür gesucht, und die obigen Antworten haben in meinem Fall nicht funktioniert (und ich habe nicht genügend Ruf, um sie zu kommentieren). Es stellte sich heraus, dass zumindest für meinen Anwendungsfall und den von mir verwendeten Browser (Chrome unter OSX) das einzige, was das Caching zu verhindern schien, Folgendes war:

Cache-Control = 'no-store'

Der Vollständigkeit halber verwende ich jetzt alle 3 von "No-Cache, No-Store, Must-Revalidate".

In meinem Fall (dynamisch generierte Bilder aus Flask in Python bereitstellen) musste ich Folgendes tun, um hoffentlich in so vielen Browsern wie möglich zu arbeiten ...

def make_uncached_response(inFile):
    response = make_response(inFile)
    response.headers['Pragma-Directive'] = 'no-cache'
    response.headers['Cache-Directive'] = 'no-cache'
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Expires'] = '0'
    return response
Kennzeichen
quelle
Nur No-Store auf die Antwort zu setzen, war genug, um es für mich zum
Laufen
Es ist nicht nur auf Chrome, auch für Firefox. Es scheint jetzt ein Standard zu sein: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control (siehe Abschnitt " Verhindern des Caching ").
Gino Mempin
3

Das Ändern der Bildquelle ist die Lösung. Sie können dies tatsächlich tun, indem Sie dem Bild einen Zeitstempel oder eine Zufallszahl hinzufügen.

Besser wäre es, eine Prüfsumme von z. B. den Daten hinzuzufügen, die das Bild darstellt. Dies ermöglicht das Caching, wenn dies möglich ist.

Stefan van Gastel
quelle
1

Fügen wir dem Bündel eine weitere Lösung hinzu.

Das Hinzufügen einer eindeutigen Zeichenfolge am Ende ist eine perfekte Lösung.

example.jpg?646413154

Die folgende Lösung erweitert diese Methode und bietet sowohl die Caching-Funktion als auch das Abrufen einer neuen Version, wenn das Image aktualisiert wird.

Wenn das Bild aktualisiert wird, wird die Dateizeit geändert.

<?php
$filename = "path/to/images/example.jpg";
$filemtime = filemtime($filename);
?>

Geben Sie nun das Bild aus:

<img src="images/example.jpg?<?php echo $filemtime; ?>" >
Daniel
quelle
1
Das habe ich wegen der Caching-Gültigkeit verwendet.
Gen
1

Ich hatte dieses Problem und überwand es so.

var newtags='<div class="addedimage"><h5>preview image</h5><img src="'+one+'?nocache='+Math.floor(Math.random() * 1000)+'"></div>';
Jordan Georgiadis
quelle
0

Ich habe dies verwendet, um mein ähnliches Problem zu lösen ... Anzeigen eines Bildzählers (von einem externen Anbieter). Es wurde nicht immer richtig aktualisiert. Und nachdem ein zufälliger Parameter hinzugefügt wurde, funktioniert alles einwandfrei :)

Ich habe eine Datumszeichenfolge angehängt, um mindestens jede Minute eine Aktualisierung sicherzustellen.

Beispielcode (PHP):

$output .= "<img src=\"http://xy.somecounter.com/?id=1234567890&".date(ymdHi)."\" alt=\"somecounter.com\" style=\"border:none;\">";

Das ergibt einen srcLink wie:

http://xy.somecounter.com/?id=1234567890&1207241014
Pinoccio
quelle
0

Wenn Sie eine fest codierte Bild-URL haben, zum Beispiel: http://example.com/image.jpg , können Sie PHP verwenden, um Ihrem Bild Header hinzuzufügen.

Zuerst müssen Sie Apache veranlassen, Ihr JPG als PHP zu verarbeiten. Siehe hier: Ist es möglich, PHP mit der Erweiterung file.php.jpg auszuführen?

Laden Sie das Bild (imagecreatefromjpeg) aus der Datei und fügen Sie die Überschriften der vorherigen Antworten hinzu. Verwenden Sie den PHP-Funktionsheader, um die Header hinzuzufügen.

Geben Sie dann das Bild mit der Funktion imagejpeg aus.

Bitte beachten Sie, dass es sehr unsicher ist, PHP JPG-Bilder verarbeiten zu lassen. Bitte beachten Sie auch, dass ich diese Lösung nicht getestet habe. Es liegt also an Ihnen, sie zum Laufen zu bringen.

Sam Sam
quelle
-1

Senden Sie einfach einen Header-Speicherort.

Meine Seite enthält ein Bild, und nach dem Hochladen des Bildes ändert sich nichts, dann füge ich diesen Code hinzu:

<?php header("Location: pagelocalimage.php"); ?>

Funktioniert bei mir.

Programmierer
quelle