web-dev-qa-db-fra.com

Désactiver le cache pour certaines images

Je génère des images en utilisant une PHP lib.

Parfois, le navigateur ne charge pas le nouveau fichier généré. 

Comment puis-je désactiver le cache uniquement pour les images créées dynamiquement par moi?

Remarque: je dois utiliser le même nom pour les images créées au fil du temps.

88
dole doug

Une solution commune et simple à ce problème qui ressemble à un hack mais qui est assez portable consiste à ajouter une chaîne de requête générée aléatoirement à chaque demande d'image dynamique.

Donc, par exemple -

<img src="image.png" />

Deviendrait

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

Ou

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

Du point de vue du serveur Web, on accède au même fichier, mais du point de vue du navigateur, aucune mise en cache ne peut être effectuée.

La génération de nombres aléatoires peut se produire sur le serveur lors de la diffusion de la page (assurez-vous simplement que la page elle-même n'est pas mise en cache ...) ou sur le client (à l'aide de JavaScript).

Vous devrez vérifier si votre serveur Web peut supporter cette astuce.

189
Hexagon

Les stratégies de mise en cache du navigateur peuvent être contrôlées par des en-têtes HTTP. N'oubliez pas qu'ils ne sont qu'un indice, vraiment. Étant donné que les navigateurs sont extrêmement incohérents dans ce domaine (et dans tout autre), vous aurez besoin de plusieurs en-têtes pour obtenir l’effet souhaité sur différents navigateurs.

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

La solution 1 n'est pas géniale. Cela fonctionne, mais l’ajout de chaînes de requête aléatoires ou horodatées à la fin de vos fichiers d’image n’est pas évolutif et oblige le navigateur à télécharger à nouveau et à mettre en cache chaque version de chaque image que vous envoyez.

La solution 2 est inutile. Ajouter des en-têtes nocache à un fichier image est non seulement très difficile à implémenter, mais il est tout à fait irréaliste, car il vous faut prévoir à quel moment vous en aurez besoin à l'avance, lors du premier chargement d'une image que vous pensez pourrait changer à un moment donné dans le futur.

Entrez Etags ...

Le meilleur moyen absolu que j'ai trouvé pour résoudre ce problème consiste à utiliser ETAGS dans un fichier .htaccess de votre répertoire images. Ce qui suit indique à Apache d'envoyer un hachage unique au navigateur dans les en-têtes du fichier image. Ce hachage ne change que lorsque le fichier image est modifié et que cette modification déclenche le navigateur pour recharger l'image à la prochaine demande.

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

Si vous avez besoin de le faire dynamiquement dans le navigateur en utilisant javascript, voici un exemple ...

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

J'ai vérifié toutes les réponses et la meilleure semblait être (ce qui n'est pas):

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

en premier.

Cependant, si vous ajoutez cache = none paramètre (qui est un mot statique "none"), cela n'a aucun effet, le navigateur se charge toujours à partir du cache.

La solution à ce problème était la suivante:

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

où vous avez essentiellement ajouté un horodatage Unix pour rendre le paramètre dynamique et pas de cache, cela a fonctionné.

Cependant, mon problème était légèrement différent: Je voulais que l'image soit lue dans le cache lorsque le paramètre d'URL GET reste inchangé et ne mette pas en cache lorsque les paramètres GET changent.

Pour résoudre ce problème, je devais hacher $ _GET mais comme c'est un tableau, voici la solution:

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

Modifier :

Bien que la solution ci-dessus fonctionne correctement, vous souhaitez parfois servir la version mise en cache jusqu'à ce que le fichier soit modifié. (avec la solution ci-dessus, le cache est complètement désactivé pour cette image).

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

filemtime () obtient l'heure de modification du fichier.

9
Tarik

Je sais que ce sujet est ancien, mais il se classe très bien dans Google. J'ai découvert que mettre cela dans votre en-tête fonctionne bien;

<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">
3
Dimitri Visser

Changer la source de l'image est la solution. Vous pouvez en effet le faire en ajoutant un timestamp ou un nombre aléatoire à l’image. 

Il serait préférable d’ajouter une somme de contrôle, par exemple les données représentées par l’image Cela permet la mise en cache lorsque cela est possible.

3
Stefan van Gastel

Je cherchais simplement une solution à ce problème et les réponses ci-dessus n'ont pas fonctionné dans mon cas (et ma réputation est insuffisante pour pouvoir les commenter). Il s'avère que, du moins pour mon cas d'utilisation et pour le navigateur que j'utilisais (Chrome sur OSX), la seule chose qui semblait empêcher la mise en cache était:

Cache-Control = 'no-store'

Pour être complet, j'utilise maintenant les 3 options suivantes: 'no-cache, no-store, must-revalidate'

Donc, dans mon cas (servir des images générées dynamiquement à partir de Flask en Python), je devais faire ce qui suit pour pouvoir travailler dans autant de navigateurs que possible ...

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

j'ai eu ce problème et surmonter comme ça. 

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

J'ai utilisé cela pour résoudre mon problème similaire ... l'affichage d'un compteur d'images (d'un fournisseur externe). Il n'a pas toujours actualisé correctement. Et après l’ajout d’un paramètre aléatoire, tout fonctionne bien :)

J'ai ajouté une chaîne de date pour assurer l'actualisation au moins toutes les minutes.

exemple de code (PHP):

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

Cela donne un lien src comme:

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

Ajoutons une autre solution au groupe.

L'ajout d'une chaîne unique à la fin est une solution parfaite. 

example.jpg?646413154

La solution suivante étend cette méthode et fournit à la fois la capacité de cache et d'extraire une nouvelle version lorsque l'image est mise à jour.

Lorsque l'image est mise à jour, le filemtime sera modifié.

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

Maintenant, affichez l'image:

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

Si vous avez une URL d'image codée en dur, par exemple: http://example.com/image.jpg vous pouvez utiliser php pour ajouter des en-têtes à votre image.

Vous devrez d’abord faire en sorte que Apache traite votre jpg en php. Voir ici: Est-il possible d'exécuter PHP avec l'extension file.php.jpg?

Chargez l'image (imagecreatefromjpeg) à partir d'un fichier, puis ajoutez les en-têtes des réponses précédentes. Utilisez l'en-tête de fonction php pour ajouter les en-têtes. 

Puis sortez l'image avec la fonction imagejpeg.

Veuillez noter qu'il est très peu sûr de laisser php traiter les images jpg. Sachez également que je n’ai pas testé cette solution et que c’est à vous de la faire fonctionner.

0
Sam Sam