Désactiver le cache pour certaines images

113

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

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.

dole doug
la source

Réponses:

233

Une solution courante 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.

Ainsi, 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 avoir lieu soit 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 ...), soit sur le client (en utilisant JavaScript).

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

Hexagone
la source
87
Au lieu de nombres aléatoires, utilisez l'horodatage de la modification des données ou un numéro de version des données reflétées.
lhunath
19
Remarque: vous n'empêchez pas réellement le navigateur de mettre en cache l'image, vous évitez uniquement de regarder l'image mise en cache. Appliquer des en-têtes appropriés à votre image est le meilleur moyen à mon humble avis (voir la solution de lhunath ci-dessous). Puisque de cette façon, vous remplissez également inutilement le cache avec des images que vous ne voulez pas mettre en cache avec le coût de réduire l'espace de cache pour les choses que vous voulez réellement mettre en cache.
Jos
Je crois que cet article explique la raison d'un tel comportement.
Metalcoder
1
cela ne fonctionne pas vraiment, l'image doit être rincée d'une autre manière (généralement lors du recadrage de l'image, l'image reste la même)
Ben
44

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 terriblement incohérents dans ce champ (et dans tout autre), vous aurez besoin de plusieurs en-têtes pour obtenir l'effet souhaité sur une gamme de navigateurs.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");
lhunath
la source
1
cela s'appliquera à toute la page ... Je ne peux pas désactiver le cache pour une seule image (une image spécifique de cette page)?
dole doug
5
@Thorpe: Cela s'applique aux réponses HTTP. Ce qui est contenu dans la réponse est sans importance. Qu'il s'agisse de données d'image, de données HTML ou autre. Si cela n'a pas fonctionné, vous ne l'avez probablement pas fait correctement. Vérifiez les en-têtes HTTP de votre réponse pour voir s'ils ont été correctement attribués.
lhunath
J'aimerais que cela fonctionne ... Chrome n'a aucun problème, mais Firefox 14 et IE 8 refusent de rafraîchir les images même avec les en-têtes ci-dessus envoyés. Cela aurait été une solution tellement plus propre que d'ajouter des paramètres arbitraires à la chaîne de requête. soupir
Pawel Krakowiak
2
@PawelKrakowiak Notez que l'ajout d'en-têtes ne fonctionnera pas pour les images qui sont déjà en cache , puisque le navigateur ne pose même pas de questions au serveur à leur sujet et ne verra donc jamais les en-têtes. Ils fonctionneront pour toutes les demandes d'image effectuées après leur ajout.
lhunath
2
Cette solution est destinée aux programmeurs, pas aux concepteurs Web. J'ai pensé que je le soulignerais parce que l'on ne peut pas simplement ouvrir et créer une image et ajouter des en-têtes à une image, à moins qu'ils ne génèrent eux-mêmes l'image dans un langage de programmation et que cela semble dérouter les commentateurs.
Bruce
13

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>
Anton Swanevelder
la source
12

La solution 1 n'est pas géniale. Cela fonctionne, mais l'ajout de chaînes de requête hacky aléatoires ou horodatées à la fin de vos fichiers image obligera le navigateur à télécharger à nouveau et à mettre en cache chaque version de chaque image, chaque fois qu'une page est chargée, quelle que soit la météo, l'image a changé ou non sur le serveur.

La solution 2 est inutile. L'ajout d'en- nocachetêtes à un fichier image n'est pas seulement très difficile à implémenter, mais c'est complètement irréalisable car cela vous oblige à prédire quand cela sera nécessaire à l'avance , la première fois que vous chargez une image qui, selon vous, pourrait changer à un moment donné dans le futur. .

Entrez Etags ...

Le meilleur moyen que j'ai trouvé pour résoudre ce problème est d'utiliser ETAGS dans un fichier .htaccess dans votre répertoire d'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 ce changement déclenche le navigateur pour recharger l'image la prochaine fois qu'elle est demandée.

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

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

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

en premier.

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

La solution à ce problème était:

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

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

Cependant, mon problème était un peu différent: je chargeais à la volée une image de graphique php générée à la volée et contrôlais la page avec les paramètres $ _GET. Je voulais que l'image soit lue à partir du cache lorsque le paramètre URL GET reste le même, et ne pas mettre en cache lorsque les paramètres GET changent.

Pour résoudre ce problème, j'avais besoin de hacher $ _GET mais comme il s'agit d'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 très bien, vous souhaitez parfois servir la version mise en cache JUSQU'À ce que le fichier soit modifié. (avec la solution ci-dessus, cela désactive complètement le cache pour cette image) Donc, pour servir l'image mise en cache à partir du navigateur JUSQU'À ce qu'il y ait un changement dans l'utilisation du fichier image:

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

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

Tarik
la source
4

Je sais que ce sujet est ancien, mais il se classe très bien dans Google. J'ai découvert que mettre ceci 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">
Dimitri Visser
la source
Les navigateurs modernes ignorent malheureusement ces directives, donc cette solution pourrait ne fonctionner que sur certains navigateurs, également, elle désactivera le cache pour tout, pas seulement pour des images spécifiques
ZioCain
4

Je cherchais juste une solution à cela, et les réponses ci-dessus n'ont pas fonctionné dans mon cas (et je n'ai pas la réputation suffisante pour les commenter). Il s'avère que, au moins pour mon cas d'utilisation et le navigateur que j'utilisais (Chrome sur OSX), la seule chose qui semblait empêcher la mise en cache était:

Cache-Control = 'no-store'

Par souci d'exhaustivité, j'utilise maintenant les 3 "no-cache, no-store, must-revalidate"

Donc, dans mon cas (servant des images générées dynamiquement à partir de Flask en Python), j'ai dû faire ce qui suit pour, espérons-le, 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
marque
la source
Le
simple
Ce n'est pas seulement sur Chrome, mais également sur Firefox. Cela semble être un standard maintenant: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control (voir la section " Empêcher la mise en cache ").
Gino Mempin
3

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

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

Stefan van Gastel
la source
1

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 mise en cache et l'extraction d'une nouvelle version lorsque l'image est mise à jour.

Lorsque l'image est mise à jour, l' heure du fichier sera modifiée.

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

Maintenant, affichez l'image:

<img src="images/example.jpg?<?php echo $filemtime; ?>" >
Daniel
la source
1
C'est ce que j'ai utilisé en raison de la validité de la mise en cache.
gène le
1

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>';
Jordan Georgiadis
la source
0

J'ai utilisé cela pour résoudre mon problème similaire ... afficher un compteur d'images (d'un fournisseur externe). Il ne s'actualisait pas toujours 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 se traduit par un srclien comme:

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

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 qu'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 du fichier puis ajoutez les en-têtes des réponses précédentes. Utilisez l'en-tête de la fonction php pour ajouter les en-têtes.

Sortez ensuite l'image avec la fonction imagejpeg.

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

Sam Sam
la source
-1

Simple, envoyez un emplacement d'en-tête.

Mon site, contient une image, et après avoir téléchargé l'image, il n'y a pas de changement, puis j'ajoute ce code:

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

Travaille pour moi.

Programador
la source