Disabilita la cache per alcune immagini


113

Genero alcune immagini usando una libreria PHP.

A volte il browser non carica il nuovo file generato.

Come posso disabilitare la cache solo per le immagini create dinamicamente da me?

Nota: devo usare lo stesso nome per le immagini create nel tempo.

Risposte:


233

Una soluzione comune e semplice a questo problema che sembra un hack ma è abbastanza portabile è aggiungere una stringa di query generata in modo casuale a ciascuna richiesta per l'immagine dinamica.

Quindi, ad esempio -

<img src="image.png" />

Potrebbe diventare

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

O

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

Dal punto di vista del web-server si accede allo stesso file, ma dal punto di vista del browser non è possibile eseguire operazioni di caching.

La generazione di numeri casuali può avvenire sul server durante il servizio della pagina (assicurati solo che la pagina stessa non sia memorizzata nella cache ...) o sul client (utilizzando JavaScript).

Dovrai verificare se il tuo server web può far fronte a questo trucco.


87
Invece di numeri casuali, utilizza il timestamp di modifica dei dati o un numero di versione dei dati riflessi.
lhunath


19
Nota: in realtà non impedisci al browser di memorizzare nella cache l'immagine, ma solo di guardare l'immagine memorizzata nella cache. Applicare intestazioni appropriate alla tua immagine è il modo migliore imho (vedi la soluzione di lhunath sotto). Poiché in questo modo si riempie inutilmente la cache con le immagini che non si desidera memorizzare nella cache con il costo di ridurre lo spazio nella cache per le cose che si desidera effettivamente memorizzare nella cache.
Jos

Credo che questo articolo spieghi il motivo di tale comportamento.
Metalcoder

1
questo non funziona davvero, l'immagine deve essere lavata in un altro modo (di solito quando si ritaglia l'immagine, l'immagine rimane la stessa)
Ben

44

Le strategie di memorizzazione nella cache del browser possono essere controllate dalle intestazioni HTTP. Ricorda che sono solo un suggerimento, davvero. Poiché i browser sono terribilmente incoerenti in questo (e in qualsiasi altro) campo, avrai bisogno di diverse intestazioni per ottenere l'effetto desiderato su una gamma di browser.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");

1
questo verrà visualizzato su tutta la pagina .... Non posso disabilitare la cache solo per un'immagine (un'immagine specifica da quella pagina)?
dole doug

5
@Thorpe: si applica alle risposte HTTP. Ciò che è contenuto nella risposta è irrilevante. Che si tratti di dati immagine, dati HTML o qualsiasi altra cosa. Se non ha funzionato, probabilmente non l'hai fatto bene. Controlla le intestazioni HTTP sulla tua risposta per vedere se sono state assegnate correttamente.
lhunath

Vorrei che funzionasse ... Chrome non ha problemi, ma Firefox 14 e IE 8 si rifiutano di aggiornare le immagini anche se vengono inviate le intestazioni di cui sopra. Questa sarebbe stata una soluzione molto più pulita rispetto all'aggiunta di alcuni parametri arbitrari alla stringa di query. sigh
Pawel Krakowiak

2
@PawelKrakowiak Nota che l'aggiunta di intestazioni non funzionerà per le immagini già memorizzate nella cache , poiché il browser non ne chiede nemmeno al server e quindi non vedrà mai le intestazioni. Funzioneranno per qualsiasi richiesta di immagine effettuata dopo averle aggiunte.
lhunath

2
Questa soluzione è destinata ai programmatori, non ai web designer. Ho pensato di farlo notare perché non si può semplicemente aprire e creare un'immagine e aggiungere intestazioni a un'immagine, a meno che non stiano generando l'immagine in un linguaggio di programmazione e questo sembra confondere i commentatori.
Bruce

13

Se devi farlo dinamicamente nel browser utilizzando javascript, ecco un esempio ...

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

12

La soluzione 1 non è eccezionale.Funziona, ma l'aggiunta di stringhe di query casuali o con timestamp alla fine dei file di immagine farà sì che il browser scarichi nuovamente e memorizzi nella cache ogni versione di ogni immagine, ogni volta che una pagina viene caricata, indipendentemente dal tempo in cui l'immagine è cambiata o meno sul server.

La soluzione 2 è inutile. L'aggiunta di nocacheintestazioni a un file di immagine non è solo molto difficile da implementare, ma è completamente impraticabile perché richiede di prevedere in anticipo quando sarà necessario , la prima volta che carichi un'immagine che pensi possa cambiare in futuro .

Inserisci Etags ...

Il modo migliore in assoluto che ho trovato per risolvere questo problema è utilizzare ETAGS all'interno di un file .htaccess nella directory delle immagini. Quanto segue dice ad Apache di inviare un hash univoco al browser nelle intestazioni del file immagine. Questo hash cambia sempre e solo quando il file immagine viene modificato e questa modifica attiva il browser per ricaricare l'immagine la volta successiva che viene richiesta.

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

11

Ho controllato tutte le risposte e la migliore sembrava essere (che non lo è):

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

All'inizio.

Tuttavia, se aggiungi cache = none parametro (che è una parola statica "none"), non ha alcun effetto, il browser viene comunque caricato dalla cache.

La soluzione a questo problema era:

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

dove fondamentalmente aggiungi timestamp unix per rendere il parametro dinamico e senza cache, ha funzionato.

Tuttavia, il mio problema era leggermente diverso: stavo caricando al volo l'immagine del grafico php generato e controllando la pagina con i parametri $ _GET. Volevo che l'immagine venisse letta dalla cache quando il parametro URL GET rimane lo stesso e non la cache quando i parametri GET cambiano.

Per risolvere questo problema, avevo bisogno di hash $ _GET ma poiché è un array, ecco la soluzione:

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

Modifica :

Sebbene la soluzione di cui sopra funzioni bene, a volte si desidera fornire la versione memorizzata nella cache FINO A CHE il file non viene modificato. (con la soluzione di cui sopra, disabilita completamente la cache per quell'immagine) Quindi, per servire l'immagine memorizzata nella cache dal browser FINO A CHE non ci sia una modifica nell'uso del file immagine:

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

filemtime () ottiene l'ora di modifica del file.


4

So che questo argomento è vecchio, ma si classifica molto bene su Google. Ho scoperto che l'inserimento di questo nella tua intestazione funziona bene;

<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">

I browser moderni purtroppo ignorano queste direttive, quindi questa soluzione potrebbe funzionare solo su alcuni browser, inoltre disabiliterà la cache per tutto, non solo per le immagini specifiche
ZioCain

4

Stavo solo cercando una soluzione a questo e le risposte sopra non hanno funzionato nel mio caso (e non ho una reputazione sufficiente per commentarle). Si scopre che, almeno per il mio caso d'uso e il browser che stavo utilizzando (Chrome su OSX), l'unica cosa che sembrava impedire il caching era:

Cache-Control = 'no-store'

Per completezza ora sto usando tutti e 3 i "no-cache, no-store, must-revalidate"

Quindi nel mio caso (che serve immagini generate dinamicamente da Flask in Python), ho dovuto fare quanto segue per poter lavorare con il maggior numero di browser possibile ...

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

Il solo fatto di non mettere in conto la risposta è stato sufficiente per farlo funzionare per me
scourge192

Non è solo su Chrome, anche per Firefox. Ora sembra essere uno standard: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control (vedere la sezione " Prevenzione della memorizzazione nella cache ").
Gino Mempin

3

Cambiare l'origine dell'immagine è la soluzione. Puoi effettivamente farlo aggiungendo un timestamp o un numero casuale all'immagine.

Sarebbe meglio aggiungere un checksum, ad esempio, ai dati rappresentati dall'immagine. Ciò abilita la memorizzazione nella cache quando possibile.


1

Aggiungiamo un'altra soluzione al gruppo.

Aggiungere una stringa univoca alla fine è una soluzione perfetta.

example.jpg?646413154

La seguente soluzione estende questo metodo e fornisce sia la capacità di memorizzazione nella cache sia il recupero di una nuova versione quando l'immagine viene aggiornata.

Quando l'immagine viene aggiornata, il filemtime verrà modificato.

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

Ora visualizza l'immagine:

<img src="images/example.jpg?<?php echo $filemtime; ?>" >

1
Questo è ciò che ho usato per la validità della memorizzazione nella cache.
gene

1

ho avuto questo problema e il superamento in questo modo.

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

0

L'ho usato per risolvere il mio problema simile ... visualizzare un contatore di immagini (da un provider esterno). Non si aggiornava sempre correttamente. E dopo che è stato aggiunto un parametro casuale, tutto funziona bene :)

Ho aggiunto una stringa di data per garantire l'aggiornamento almeno ogni minuto.

codice di esempio (PHP):

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

Ciò si traduce in un srccollegamento come:

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

0

Se hai un URL immagine hardcoded, ad esempio: http://example.com/image.jpg puoi usare php per aggiungere intestazioni alla tua immagine.

Per prima cosa dovrai fare in modo che apache elabori il tuo jpg come php. Vedi qui: È possibile eseguire PHP con estensione file.php.jpg?

Carica l'immagine (imagecreatefromjpeg) dal file quindi aggiungi le intestazioni dalle risposte precedenti. Usa l'intestazione della funzione php per aggiungere le intestazioni.

Quindi visualizza l'immagine con la funzione imagejpeg.

Si noti che è molto insicuro lasciare che php elabori le immagini jpg. Inoltre, tieni presente che non ho testato questa soluzione, quindi spetta a te farlo funzionare.


-1

Semplice, invia una posizione di intestazione.

Il mio sito, contiene un'immagine, e dopo aver caricato l'immagine, non cambia, quindi aggiungo questo codice:

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

Per me va bene.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.