Estos días he tenido la necesidad de trabajar con un formulario de subida de imágenes y he tenido que montar una zona para mostrar la preview de las imágenes antes de subirlas al servidor para que el usuario pueda comprobar si todo es correcto antes de completar la operación. Hace algún tiempo (algunos años) creo recordar que vi alguna respuesta del gran Pedro Hurtado en los foros de MSDN acerca de esta cuestión pero no he podido encontrar dónde lo vi. Así que lo posteo para intentar ayudar a quien se encuentre en este caso y no sepa cómo alcanzar la solución.
Bien, como os iba contando, necesitamos que antes de subir las imágenes al servidor, el usuario pueda ver qué es lo que va a subir. Entre otras muchas soluciones, creo que una de las más adecuadas es usar la cadena en base64 que forma la imagen. ¿Qué? ¿Aún no sabías que se podía hacer? Es probablemente lo que oirías de muchas personas que tienen mucha experiencia, pero como no nacemos con un manual sobre desarrollo web en la cabeza, algún día tendréis que aprender al igual que yo lo aprendí del mencionado foro con la respuesta de Pedro, así que vamos a ver cómo se muestra una imagen:
- Desde una url pública –> <img src=”http://DOMINIO/IMAGEN.XXX” />
- Desde una url absoluta del proyecto –> <img src=”/DIRECTORIO/IMAGEN.XXX” />
- Desde una url relativa del proyecto –> <img src=”../DIRECTORIO/IMAGEN.XXX” />
- Usando base64 –> <img src=»data:image/jpeg;base64{binary data}» />
Hasta aquí todo perfecto y fácil de entender. Esto se ha usado por ejemplo cuando se guardaban imágenes en un campo de una tabla en la base de datos y se querían mostrar en pantalla. Pero bien, ahora ¿cómo lo aprovecho para hacerlo desde el navegador del usuario para poder mostrar una preview de una imagen? Bueno, para esto entre otras tantas soluciones, podremos aprovechar las capacidades con JavaScript de nuestros navegadores modernos (espero que los tengáis actualizados y no me valen excusas), así que vamos a usar la api de ficheros (File) y en concreto vamos a trabajar con FileReader.
Ejemplo:
HTML
<div id="divInputLoad">
<h1>Test it uploading your own image</h1>
<div id="divFileUpload">
<input id="file-upload" type="file" accept="image/*" />
</div>
<div id="file-preview-zone">
</div>
</div>
JavaScript
<script>
function readFile(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var filePreview = document.createElement('img');
filePreview.id = 'file-preview';
//e.target.result contents the base64 data from the image uploaded
filePreview.src = e.target.result;
console.log(e.target.result);
var previewZone = document.getElementById('file-preview-zone');
previewZone.appendChild(filePreview);
}
reader.readAsDataURL(input.files[0]);
}
}
var fileUpload = document.getElementById('file-upload');
fileUpload.onchange = function (e) {
readFile(e.srcElement);
}
</script>
Como podéis observar, lo que hago es conectarme al evento “onchange” del control de selección de ficheros (al que he puesto que sólo por defecto busque imágenes) y, en cuanto reciba un cambio, se ejecuta la función readFile que recoge como parámetro el control. Se comprueba si tiene un fichero y, en caso de tenerlo (el ejemplo es para un único fichero), se crea una nueva instancia de FileReader y ejecuta la función “readAsDataURL” que leerá el fichero desde la ruta en disco.
Una vez leído el fichero, se ejecutará la función suscrita al evento “onload” de la instancia de FileReader. Entonces, se crea el DOM del elemento img donde se va a mostrar la preview y se le asigna como source “src” el resultado de la lectura del fichero que, por supuesto, está en base64. E voilà! Ya tenemos la preview de la imagen sin haberla subido al servidor.
Aquí tienes el código de ejemplo
Excelente explicación. Muchas gracias.
¿podrías decirme como hacer para que las imágenes previsualizadas estén en un tamaño proporcionado? es decir, quiero verlas pero no en su tamaña original sino en uno mas pequeño ya que me descoloca toda la web. Gracias
Hola Jonathan.
Gracias por leer el artículo.
Tendrías que hacerlo por CSS o mediante JavaScript estableciendo los parámetros width y height