2009-09-06 30 views
20

Soy totalmente nuevo en la forma de almacenar imágenes en caché.¿Cómo hacer que el navegador guarde en caché las imágenes con php?

Imprimo todas las imágenes en una galería con php, y quiero que las imágenes ya mostradas, sean almacenadas en la memoria caché por el navegador, por lo que el script php no tiene que mostrar la misma imagen nuevamente. Todo lo que quiero es que las imágenes aparezcan más rápido.

cuando se llama a una imagen que hago de esta manera:

<img src="showImage.php?id=601"> 

y la showImage.php -file Hace:

$resultat = mysql_query(" 
    SELECT filename, id 
    FROM Media 
    WHERE id = '".$_GET['id']."' 
"); 
$data = mysql_fetch_assoc($resultat); 

... 

//Only if the user are logged in 
if(isset($_SESSION['user'])){ 
    header("Content-Type: image/jpeg"); 

    //$data['filename'] can be = dsSGKLMsgKkD3325J.jpg 
    echo(file_get_contents("images/".$data['filename']."")); 
} 
+0

No estoy seguro de lo que está tratando de lograr, a partir de su pregunta original sonaba como si estuviera generando imágenes sobre la marcha y quería almacenar en caché las imágenes generadas en la primera carga y servir desde el disco en cargas posteriores. ¿Estás hablando de caché del navegador? –

+1

¿Por qué está usando un script PHP de todos modos? – Gumbo

+0

Sí, quiero que el navegador guarde en caché la imagen. – Johan

Respuesta

4

Si está utilizando php para verificar si el usuario ha iniciado sesión antes de enviar el mensaje, entonces no desea que el navegador guarde en caché la imagen.

El objetivo de todo el almacenamiento en caché es llamar al servidor una vez y luego nunca volver a llamarlo. Si el navegador almacena en caché la imagen, no llamará al servidor y su secuencia de comandos no se ejecutará. En cambio, el navegador extraerá su imagen de la memoria caché y la mostrará, incluso si el usuario ya no está conectado. Esto podría ser un agujero de seguridad muy grande.

+0

Hm, ese es un buen punto. Pero estaría bien almacenar la imagen una hora difícil. – Johan

+1

Incluso una hora no es segura, todo lo que hace es esperar que los hackers no intenten piratear en un momento determinado. Sin embargo, por lo que puedo ver en http://www.mnot.net/cache_docs/#SCRIPT, parece que puede forzar la autenticación con el almacenamiento en caché utilizando 'Cache-control: public, no-cache;' en su encabezado HTTP ('no-cache' en realidad no significa que no haya almacenamiento en caché, los nombres están un poco apagados). – Imagist

+3

Aún puede almacenar en caché * y * hacer que el navegador llame al servidor. Se llama validación de caché. Para ello, envíe 'Cache-control: private, must-revalidate' (privado, ya que no debe compartirse entre usuarios) y el encabezado' Last-Modified' o 'ETag'. Luego, cuando el navegador envía 'If-Modified-Since' o' If-None-Match' responden con el estado '304' si nada ha cambiado desde que se generó la imagen. – Kornel

48

En primer lugar, si usted está usando sesiones, debe desactivar session_cache_limiter (estableciéndolo en none o public). Los encabezados que envía son bastante malos para los cachés.

session_cache_limiter('none'); 

Entonces enviar Cache-Control: max-age=number_of_seconds y, opcionalmente, una cabecera equivalente Expires:.

header('Cache-control: max-age='.(60*60*24*365)); 
header('Expires: '.gmdate(DATE_RFC1123,time()+60*60*24*365)); 

Para el mejor cacheability, enviar Last-Modified cabecera y responder con el estado 304 y el cuerpo vacío si el navegador envía una cabecera If-Modified-Since a juego.

header('Last-Modified: '.gmdate(DATE_RFC1123,filemtime($path_to_image))); 

Por razones de brevedad que estoy engañando aquí un poco (el ejemplo no verifica la fecha), pero es válida siempre y cuando no te importa navegadores mantener el archivo en caché para siempre:

if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { 
    header('HTTP/1.1 304 Not Modified'); 
    die(); 
} 
+0

Sí, estoy usando 'sessions'. Hm, parece que dices que es lo que necesito, pero no entiendo cómo unirlo al código de trabajo. ¿Cómo escribo si quiero que el navegador guarde en caché la imagen durante un año? – Johan

+0

Muchas gracias, ¡es perfecto para mí! gracias gracias thnaks! :) – ParisNakitaKejser

+0

El bit '' If-Modified-Since'' es el "d'oh" o "eureka!" momento, ¡lo que prefieras! – Agamemnus

3

se podría almacenar las imágenes generadas en un directorio llamado "ShowImage" para que le incrustarlos como esto

<img src="showimage/601.jpg" /> 

Luego se coloca un archivo .htaccess en el mismo directorio que se llame showImage.php? id = en caso de que no existe el archivo, por ejemplo:

<IfModule mod_rewrite.c> 
    RewriteEngine On 
    RewriteCond %{REQUEST_FILENAME} !-f 
    RewriteRule ^(.*)\.jpg$ showImage.php?id=$1 [QSA,L] 
</IfModule> 

acabamos de leer en su comentario que desea hacer el almacenamiento en caché del lado del cliente: acaba de establecer las cabeceras HTTP caché-relacionado de acuerdo a http://www.mnot.net/cache_docs/


Por favor, tenga en cuenta que la consulta es vulnerable a inyecciones SQL, porque no desinfectar/escapar $ _GET [ 'id']: http://php.net/mysql_real_escape_string

0

Por favor, las imágenes de direcciones no son algunos recursos id'ed. utilice las URL absolutas para las imágenes, preferiblemente en un subdominio, preferiblemente menos cookies. El navegador hará el almacenamiento en caché de las imágenes. Un buen truco para cargar imágenes más rápido en los sitios web es colocarlo en algún CDN u otro sitio. Esto porque los navegadores limitan el número de subprocesos de solicitud paralelos a un dominio.

Otra manera ordenada de trabajar con imágenes es el sprite, búscalo. Ahorra mucho ancho de banda y también solicitudes.

También puede utilizar la carga directa de mapa de bits si la velocidad es tan crucial.Sin embargo, esto no se recomienda para imágenes grandes. Si sus iconos y pequeñas imágenes/gifs que está cargando. Puede usar mapas de bits directamente en la página.

7

Aquí hay un código que utilizo para el apoyo 304 de cabecera:

/** 
    * @return false if not cached or modified, true otherwise. 
    * @param bool check_request set this to true if you want to check the client's request headers and "return" 304 if it makes sense. will only output the cache response headers otherwise. 
    **/  
    protected function sendHTTPCacheHeaders($cache_file_name, $check_request = false) 
    { 
    $mtime = @filemtime($cache_file_name); 

    if($mtime > 0) 
    { 
     $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT'; 
     $etag = sprintf('%08x-%08x', crc32($cache_file_name), $mtime); 

     header('ETag: "' . $etag . '"'); 
     header('Last-Modified: ' . $gmt_mtime); 
     header('Cache-Control: private'); 
     // we don't send an "Expires:" header to make clients/browsers use if-modified-since and/or if-none-match 

     if($check_request) 
     { 
     if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && !empty($_SERVER['HTTP_IF_NONE_MATCH'])) 
     { 
      $tmp = explode(';', $_SERVER['HTTP_IF_NONE_MATCH']); // IE fix! 
      if(!empty($tmp[0]) && strtotime($tmp[0]) == strtotime($gmt_mtime)) 
      { 
      header('HTTP/1.1 304 Not Modified'); 
      return false; 
      } 
     } 

     if(isset($_SERVER['HTTP_IF_NONE_MATCH'])) 
     { 
      if(str_replace(array('\"', '"'), '', $_SERVER['HTTP_IF_NONE_MATCH']) == $etag) 
      { 
      header('HTTP/1.1 304 Not Modified'); 
      return false; 
      } 
     } 
     } 
    } 

    return true; 
    } 
Cuestiones relacionadas