¿Vale la pena cambiar toda la estructura de archivos de imágenes de mi usuario para aprovechar el almacenamiento en caché simple del navegador?

9

En uno de mis sitios móviles, simplemente almaceno las imágenes de perfil de mi usuario como '1.jpg' en su carpeta de usuario, y voy progresivamente desde allí para ver las fotos adicionales que cargan. Esto significa que cada vez que cambian su foto de perfil, por ejemplo, el nombre del archivo permanece igual.

He querido aprovechar el almacenamiento en caché de imágenes para que la misma foto antigua no se descargue una y otra vez cada vez que se ve y se vuelve a ver el perfil de un usuario, pero al mismo tiempo, quiero que los navegadores de mis usuarios descargue el nuevo si ha cambiado.

Por lo que he estado leyendo, parece que la única forma de hacer esto realmente es usar nombres de archivos aleatorios y realizar un seguimiento de todos esos nombres de archivos en la base de datos, para que pueda configurar un caché que no caduque, mientras que recientemente las fotos cambiadas se vuelven a extraer ya que tienen un nuevo nombre de archivo. Sin embargo, la belleza de la forma en que los he estructurado hasta ahora es que puedo omitir la base de datos por completo y acceder a los archivos directamente, ya que su ubicación es predecible.

Entonces, mi pregunta es, ¿vale la pena para mí cambiar la estructura de archivos completa de mi sitio, además de agregar el elemento DB, en beneficio del almacenamiento en caché eterno y la descarga automática después de una nueva carga?

Esta es una tarea enorme, pero si se considera digna, no tengo ningún problema para avanzar con este cambio drástico. Solo quiero asegurarme de que así es como lo hacen los "chicos grandes" para que nunca tenga que cambiar la estructura del archivo nunca más.

Gracias.

ProgrammerGirl
fuente

Respuestas:

7

Una solución de uso común es hacer que las URL de sus imágenes se vean así:

http://www.example.com/path/to/images/1.jpg?v=123456

Aquí, /path/to/images/1.jpgestá la ruta URL real de la imagen, mientras que ?v=123456es solo una consulta ficticia que se encuentra pegada al final de la URL. La cadena de consulta puede ser cualquier cosa: un número de versión, una marca de tiempo, un hash del contenido de la imagen, siempre que la cambie cada vez que cambie la imagen y la mantenga igual cuando no lo haga.

El truco es que el servidor web, cuando se le pide que sirva dicha URL, ignorará la cadena de consulta, ya que la URL de hecho apunta a un archivo estático. Pero para el navegador del usuario (y para cualquier proxy intermedio), las URL con diferentes cadenas de consulta serán completamente diferentes, por lo que cualquier cambio en la cadena de consulta obliga al navegador a recargar el archivo.

Por lo tanto, puede configurar su servidor web para enviar Expiresy Cache-Controlencabezados HTTP para permitir el almacenamiento en caché indefinido, seguro sabiendo que puede forzar una recarga cambiando la cadena de consulta. Una forma de hacerlo, si está usando Apache con mod_expires , es colocar un .htaccessarchivo en su directorio de imágenes con las líneas:

ExpiresActive On
ExpiresDefault "access plus 1 year"

Esta técnica es utilizada por muchos sitios web populares. Por ejemplo, si observa la fuente HTML de esta misma página, encontrará que la hoja de estilo se carga desde una URL como esta:

http://cdn.sstatic.net/stackoverflow/all.css?v=7cd8ea9d6f1e

Aquí, el ?v=7cd8ea9d6f1ees una cadena de consulta ficticia tal como lo describí anteriormente; puede confirmarlo cambiándolo y ver que de hecho todavía devuelve el mismo archivo.

Ilmari Karonen
fuente
También es interesante, pero ¿cómo haría un seguimiento de cuándo se modificó por última vez el archivo y cuándo se vio por primera vez el navegador, para determinar cuándo debo decirle al navegador del usuario que vuelva a buscarlo (por ejemplo, cambiando el valor de la consulta)?
ProgrammerGirl
1
No necesita realizar un seguimiento cuando se vio el archivo. Simplemente realice un seguimiento de cuándo se modificó el archivo por última vez (o alguna otra propiedad apropiada del mismo) e inclúyalo en la cadena de consulta. De esa manera, cada vez que cambie el archivo, la URL también cambiará.
Ilmari Karonen
Muy, muy interesante. Entonces, presumiblemente, podría obtener la propiedad "última modificación" de los archivos, y simplemente hacer que el valor de la consulta, ¿correcto?
ProgrammerGirl
1
Sí, eso debería funcionar.
Ilmari Karonen
1
No hay inconvenientes significativos que yo sepa. Es posible que termine con copias duplicadas de sus imágenes en los índices de los motores de búsqueda, pero al menos los principales motores de búsqueda como Google son bastante inteligentes al tratar con esas cosas, ya que es un truco tan común. En cualquier caso, ese problema puede mitigarse enviando encabezados HTTP rel = "canonical" y manteniendo moderados los tiempos de vencimiento (por ejemplo, solo un mes o una semana en lugar de un año completo).
Ilmari Karonen
6

Hay más de una forma de almacenar en caché.

Obtener condicional

Si está almacenando estas imágenes en el sistema de archivos y sirviéndolas directamente a través del servidor web, probablemente ya esté utilizando get condicional . El servidor web utilizará automáticamente los metadatos del sistema de archivos para establecer un encabezado ETAG y responderá automáticamente con "304 no modificado" si el navegador incluye If-Modified-Sinceo If-Matchesencabezados en su solicitud. (Todos los navegadores lo harán).

En este caso, la imagen completa no se devuelve, por lo que tiene ahorros de ancho de banda. Sin embargo, aún se emitirá una solicitud GET, por lo que aún tendrá los gastos generales y la latencia de una solicitud.

Puede disminuir ligeramente el número de solicitudes a expensas de la actualización de la memoria caché haciendo que su servidor web establezca Cache-Controlencabezados con un public,max-age=Nvalor para sus imágenes. Esto dice que los cachés pueden conservar el recurso durante la mayoría de los max-agesegundos antes de que tengan que verificar si está actualizado.

Sin embargo, HTTP define solo una forma de invalidar una entrada de caché, que puede no ajustarse a la semántica de su aplicación: si PUBLICA o PONE a una url que actualiza la foto de perfil, responda con un Location: [url of photo]encabezado y la entrada de caché para esa url se invalidará.

(Este es el mecanismo que le permite almacenar en caché una página web con comentarios, y luego hacer que el navegador vuelva a cargar la página a la fuerza después de que el usuario publique un nuevo comentario. El navegador respondería a POST /commentcon 303 See Othery a Location: /page/with/comment. Tenga en cuenta que esto no se utilizó trabajar en Firefox debido a un error de larga data )

A menos que tenga mucho tráfico, este enfoque para el almacenamiento en caché está bien.

Cambio de URL

Una url es una representación de un recurso, por lo que otra forma de administrar el almacenamiento en caché no es cambiar los parámetros de caché para el recurso, sino crear un nuevo recurso con una directiva de "caché para siempre". Este es el enfoque que favorecen los "chicos grandes", porque les permite no generar solicitudes adicionales, lo que les ahorra mucho ancho de banda. La desventaja es que requiere mucha más contabilidad adicional.

Hay dos técnicas generales para esto.

Consultar cadenas

Los servidores web ignoran las cadenas de consulta cuando sirven un archivo desde el sistema de archivos. Sin embargo, los cachés no lo hacen: /1.jpg?t=12345y /1.jpg?t=67890son dos recursos completamente diferentes y no relacionados, aunque el servidor piense que son iguales.

Entonces, una cosa fácil que puede hacer es agregar la marca de tiempo del sistema de archivos como una cadena de consulta cada vez que haga una referencia a un recurso en su html y establezca un Expiresencabezado largo . El navegador entonces almacenar en caché este recurso siempre y no hacer ninguna GET, siempre y cuando la cadena de consulta no cambia.

Un inconveniente es que es difícil o imposible instruir al servidor web de la nueva url para un elemento si desea invalidar por la fuerza un caché. Por ejemplo, si un navegador tiene una página HTML en caché con una /1.jpg?v=1referencia, pero por casualidad borró la entrada /1.jpg?v=1(tal vez se quedó sin espacio de archivo o memoria), realizará una nueva solicitud /1.jpg?v=1. Si mientras tanto la imagen ha cambiado a /1.jpg?v=2, la respuesta adecuada es:

  1. Servir la versión anterior del archivo. Haría esto si quisiera que todos los recursos sean coherentes entre sí, como lo fueron en un determinado momento. Esto es lo que debe hacer con los archivos CSS, por ejemplo, ya que un nuevo archivo CSS con un viejo archivo HTML puede no funcionar correctamente.
  2. Redireccionar a la nueva versión del archivo usando 301 Moved Permanently. Haría esto si quisiera que todos los recursos sean lo más nuevos posible.

Ambos son difíciles de hacer solo con un servidor web, lo que significa que debe invocar una aplicación web incluso para solicitudes de imágenes, que pueden ser más complicadas y requerir más recursos. Los servidores web son muy rápidos para servir archivos, por lo que la sobrecarga de una aplicación web puede terminar tragándose el ancho de banda y las ganancias de latencia.

Nombres de archivo

En lugar de agregar una cadena de consulta, cambia el nombre del archivo. Esto significa que es fácil mantener varias versiones de archivos en el sistema de archivos, pero probablemente necesitará almacenar metadatos de archivos y hacer otra contabilidad de la base de datos para realizar un seguimiento de sus recursos y sus nombres.


fuente
0

lea sobre el estado de http 304 Not Modified, debería poder responder a una solicitud de descarga con 304, y de ese modo decirle al servidor que use los datos en caché, en lugar de reenviarlos al navegador. y lea esta pregunta /programming/2978496/make-php-page-return-304-not-modified-if-it-hasnt-been-modified

Puggan Se
fuente
Interesante, pero ¿es esta una solución de "ayuda de banda" para un esquema de archivo problemático, o mi esquema de archivo es bueno y solo necesita esta capacidad de almacenamiento en caché? Además, ¿cómo sabría cuándo se modificó por última vez el archivo y cuándo se vio por primera vez el navegador, para determinar cuándo debo decirle al navegador del usuario que vuelva a buscarlo?
ProgrammerGirl
No estoy tan familiarizado con él, creo que Francis Avila sabe mucho más sobre eso
Puggan Se