Menú Cerrar

Recargar imágenes con el mismo nombre de archivo

A veces, por conveniencia y diseño de la base de datos, se mantiene el nombre de los archivos aunque se vuelvan a subir nuevos y distintos, dependiendo del caso esto es muy válido o profundamente incorrecto. Es fácil verlo en zonas privadas de usuarios. El típico caso en el que un usuario se cambia el avatar, sube su foto nueva y aunque todo parece correcto, su foto sigue siendo la misma de antes.

Esto ocurre porque los navegadores y proxys guardan los archivos en sus caches previendo futuras solicitudes. Si se acaba de cargar una página con una imagen y se le vuelve a pedir que se cargue lo que parece la misma imagen, la sirve desde el caché. Un ejemplo sencillo: la tabla de usuarios de la base de datos tiene el típico campo id, además de otros como el nombre, avatar, etc. El id se usa para darle nombre a la imagen del avatar. En la página en cuestión hay un formulario para subir el avatar mediante AJAX que muestra una ruleta animada mientras va subiendo. Si no hay error se cambia dinámicamente con Javascript el valor del campo src de la <img/> que contiene el avatar y así se forzaría la carga de la imagen nueva. El usuario Juan tiene el id 27 y el archivo de su avatar se llama avatar-27.jpg, quiere cambiar su foto que se hizo en verano por otra que se ha hecho en invierno con un gorro con borla, la imagen la tiene en jpg. La sube y cuando termina el proceso de subida sigue viéndose en bañador con la playa detrás. Si la imagen es de otro tipo y no se manipula en el servidor para que sea del mismo siempre, no tiene porque haber ningún problema, avatar-27.png != avatar-27.jpg. En caso de que haya una política de nombres rígidos si que hay un problema. Esto también puede ocurrir al recargar la página, aunque lo he visto en menos ocasiones.

La única solución es pedirle al navegador una imagen con otro nombre, hay dos formas de hacerlo:

  1. Añadirle algo al nombre para que le parezca distinto al navegador.
  2. Cambiar la política de nombres para las imágenes al subirlas.

La opción 1 es fácil de implementar. Se añade dinámicamente con Javascript la interrogación «?» que se utiliza para marcar el inicio de los parámetros GET y después un texto aleatorio. No hace falta ni poner un parámetro y su «=» correspondiente. Si el servidor no espera este parámetro para tratarlo no afecta a la carga de la imagen y para el navegador es un nombre de archivo distinto:

// sin cambiar el nombre, inocuo completamente, sustituir algo por lo mismo...
if(subidaOk) document.getElementById("avatar").src="avatar-27.jpg";

// añadiendo "?" y con Math.random() un número aleatorio
if(subidaOk) document.getElementById("avatar").src="avatar-27.jpg?"+Math.random();

La forma más sencilla de conseguir un texto para añadirlo dinámicamente es utilizar la función de Javascript Math.random(), que generará un número aleatorio entre 0 y 1, el cual siempre tendrá muy poca probabilidad de repetirse en dos cargas seguidas y cumple como cadena de texto aleatoria.

En caso de que se recargue la página recomiendo añadir el número aleatorio en el servidor. Con PHP se podría utilizar rand() y sería:

<img src="avatar-27.jpg?<?php echo rand();?>"/>

La opción 2 es cuestión del diseño del proceso. Si se guarda el nombre en la base de datos se puede establecer como se quiera, con números y/o letras al azar, mientras se generen nombres de archivos válidos. Recomiendo que lleve una parte rígida con el id y después un texto de una longitud establecida. Si por ejemplo la parte rígida contiene la «avatar» + «-» + id + «-» +cadena aleatoria de 6 caracteres (por ejemplo), se consiguen nombre imposibles de duplicar. «avatar-» (o cualquier otra cosa) la llevaran todos los nombres pero el id será siempre único y distinto, si el diseño de la base de datos es mínimamente correcto. La cadena aleatoria tendrá sólo la función de diferenciar imágenes del mismo usuario.