2009-06-08 9 views
3

J'ai un gestionnaire personnalisé qui renvoie une image au navigateur.Pourquoi ma mise en cache d'image personnalisée n'est-elle pas disponible dans le navigateur?

Les images sont extraites d'une base de données.

Pour une raison quelconque les images ne sont pas mises en cache par le navigateur, et je me demandais si quelqu'un pourrait être en mesure de repérer ce que je suis absent du code ci-dessous:

HttpContext.Current.Response.BinaryWrite(imageBytes); 
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Public); 
Context.Current.Response.Cache.SetAllowResponseInBrowserHistory(true); 
if(imgRepGetCache.DateCached.HasValue) 
    HttpContext.Current.Response.Cache.SetLastModified(imgRepGetCache.DateCached.Value); 
HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.AddDays(2)); 
HttpContext.Current.Response.ContentType = "image/jpeg"; 

Ou bien si je suis manquant complètement le point en quelque sorte et il y a un autre endroit où je dois regarder.

Edit: selon la demande pour plus d'informations:

  • L'URL est toujours le même
  • Je teste le chargement du même fichier via le tuyau standard IIS et ma pipe dans le même navigateur sur la même PC. Celui qui charge via IIS est normalement mis en cache, mon fichier ne l'est pas.

Edit 2: Après avoir inspecté les requêtes HTTP/réponses sur la route IIS normale, je pense qu'il a quelque chose à voir avec le ETag. Le ETag (que je suis nouveau à partir de maintenant) semble être une sorte de checksum pour le document. Lors de demandes ultérieures par un navigateur, l'ETag est envoyé et si le serveur trouve que l'ETag n'a pas changé, il renvoie un 304 - Non Modifié. Tout bon! Mais je suis en train de paramétrer l'ETag en utilisant:

HttpContext.Current.Response.Cache.SetETag(imgRepGetCache.DateCached.ToString()); 

Mais cela n'apparaît pas dans la réponse. Plus près ...

Édition 3: Je l'ai résolu à la fin après avoir profité de Firebug pour un peu d'amusement inspectant HTTP. J'ai posté ma solution ci-dessous.

+0

Vous devriez publier plus d'informations. Parfois, les navigateurs ne sont pas mis en cache en fonction de l'URL de la page ou des métadonnées associées à la page en cours de rendu, ou même en raison de paramètres locaux. – Kieveli

+0

Certains (je ne sais pas lequel) ne mettra pas non plus en cache les pages basées sur des suffixes, ie. ils ne mettront pas en cache les pages php, car elles sont connues pour être des contenus dynamiques. –

+0

Point très utile à faire! Je me souviendrai de cela pour tous les futurs f *** s de la mise en cache. – joshcomley

Répondre

3

OK, je l'ai corrigé.

Voici ce que je l'ai fait pour quelqu'un d'autre et pour ma propre référence future:

// Check for repeated request for the same image from a browser 
if (HttpContext.Current.Request.Headers.Get("If-None-Match") == imgRepGetCache.DateCached.Value.ToString()) 
{ 
    // Return 304 - Not Modified 
    HttpContext.Current.Response.Status = "304 Not Modified"; 
} 
else 
{ 
    if (imgRepGetCache.DateCached.HasValue) 
     HttpContext.Current.Response.Headers.Set("Etag", imgRepGetCache.DateCached.Value.ToString()); 
    // ... do my other stuff here 
} 

Works un charme!

Si quelqu'un trouve des problèmes potentiels ici, faites le moi savoir afin que je puisse mettre à jour cela.

Pour en préempter un évident - je peux 100% compter sur la chaîne de date pour identifier si une image est nouvelle ou non (dans mon scénario particulier).

0

Vous ne mentionnez rien dans votre message à ce sujet, mais est-ce une adresse https: //? Les navigateurs ne mettent pas en cache les images et les pages des sites https pour des raisons de sécurité.

+0

Point intéressant, mais ce n'est pas (pour le moment, de toute façon). Merci! – joshcomley

+1

Ce n'est pas vrai. Les navigateurs peuvent mettre en cache le contenu https s'il possède un en-tête 'cache-control: public', en plus de l'en-tête standard expires. Firefox sera définitivement mis en cache s'il voit cet en-tête. – Chi

0

Les choses dont vous avez besoin à vous soucier de la génération de la réponse sont:

  • ETag
  • Expires

Les choses que vous devez à vous soucier lors de la réception d'une requête sont:

  • Last-Modified
  • If-Match
  • If-None-Match
  • If-Modified-Since
  • Si-Unmodified-Since
  • Vous pouvez également moins-Modified-Since

à se soucier de la suivant les méthodes http:

  • GET
  • TÊTE

Voici une solution qui devrait être assez facile à factoriser à la suite vos besoins: http://code.google.com/p/talifun-web/wiki/StaticFileHandler

Il lit les fichiers du système de fichiers et les les place dans un cache en mémoire, il suffit de changer à lire base de données. Devrait être un travail facile.

+0

pourriez-vous s'il vous plaît jeter un oeil à [cette question] (http://stackoverflow.com/questions/19346048/how-to-setup-talifunweb-staticfilehandler-with-a-virtualpathprovider)? – superjos