En el post anterior vimos cómo acceder a la metadata de los archivos locales que el usuario insertaba en nuestro sitio, a través de la etiqueta input o bien haciendo uso de los eventos Drag and Drop.
En esta ocasión vamos a ver cómo podemos leer esos archivos desde el lado del cliente de manera asíncrona :D. Para ello haremos uso de la interfaz FileReader, la cual nos ofrece distintos mecanismos de tratamiento a través del objeto File: readAsDataURL, readAsText, readAsArrayBuffer y readAsBinaryString. En este artículo vamos a centrarnos en los dos primeros, ya que creo que es una forma realmente buena de mejorar la experiencia de usuario.
FileReader.readAsDataURL
Esta opción nos va a permitir recuperar como resultado un archivo como una URL codificada. Una forma muy simple de probar este supuesto es a través de un archivo de tipo imagen. Para ello, tenemos el siguiente ejemplo:
En esta demostración de lo que se trata es de añadir una serie de imágenes con el objetivo de obtener una vista previa de cada una de ellas. Una vez adjuntadas y generada la miniatura podemos observar que el source es el archivo codificado en base 64 directamente inyectado como fuente de la etiqueta de imagen. ¿Cómo lo hacemos?
window.onload = function() { //Check File API support if (window.File && window.FileList && window.FileReader) { var filesInput = document.getElementById("files"); filesInput.addEventListener("change", function(event) { var files = event.target.files; //FileList object var output = document.getElementById("result"); for (var i = 0; i < files.length; i++) { var file = files[i]; //Only pics if (!file.type.match('image')) continue; var picReader = new FileReader(); picReader.addEventListener("load", function(event) { var picFile = event.target; var div = document.createElement("div"); div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" + "title='" + picFile.name + "'/>"; output.insertBefore(div, null); }); //Read the image picReader.readAsDataURL(file); } }); } else { console.log("Your browser does not support File API"); } }
En este caso, para tener claro cuáles son los requisitos mínimos, he comprobado que nuestro navegador soporta window.File, window.FileList y window.FileReader ya que son las tres interfaces involucradas para este ejemplo. Exactamente igual que en post anterior controlo el cambio del input que recibe las imágenes, con el objetivo de procesar todas ellas una vez cargadas en el navegador. Gracias al objeto FileList devuelto por e.target.files podré recorrerme todos los archivos selecionados y así procesar el contenido. Dentro del bucle, comprobaré si el archivo adjuntado es una imagen, o continuaré con el siguiente. En el caso de que así sea crearé un objeto del tipo FileReader y, antes de ejecutar la lectura, me suscribiré al evento load para ser consciente de cuándo podré mostrar el resultado, en este caso, a través de una etiqueta de tipo imagen incluida dentro de un div. Una vez que tengo establecido qué voy a hacer con el resultado podré llamar a readAsDataURL.
FileReader.readAsText
En el caso de que queramos tratar texto la manera de hacerlo es igual de sencilla 😀
En este supuesto el código ha sido modificado, cambiando el comportamiento del evento load donde únicamente se inyecta el resultado en un div y, por otro lado, se utiliza readAsText en lugar de readAsDataURL.
window.onload = function() { //Check File API support if (window.File && window.FileList && window.FileReader) { var filesInput = document.getElementById("files"); filesInput.addEventListener("change", function(event) { var files = event.target.files; //FileList object var output = document.getElementById("result"); for (var i = 0; i < files.length; i++) { var file = files[i]; //Only plain text if (!file.type.match('plain')) continue; var picReader = new FileReader(); picReader.addEventListener("load", function(event) { var textFile = event.target; var div = document.createElement("div"); div.innerText = textFile.result; output.insertBefore(div, null); }); //Read the text file picReader.readAsText(file); } }); } else { console.log("Your browser does not support File API"); } }
Para comprobar el mismo podéis hacerlo adjuntando un archivo de texto plano o bien a través de este que os facilito aquí: Lore ipsum.txt 🙂
Por último, os listo cada uno de los eventos a los cuales nos podemos suscribir para su manejo:
- loadstart: Cuando la lectura comienza.
- progress: Mientras se está leyendo (y codificando).
- load: La lectura ha finalizado correctamente.
- abort: La lectura ha sido abortada. Se puede llevar a cabo llamando al método abort().
- error: La lectura ha fallado.
- loadend: La petición de lectura ha finalizado.
Espero que haya sido de utilidad 🙂
Demos completas:
File API – FileReader (readAsDataURL)
File API – FileReader (readAsText)
¡Saludos!