HTML5 Apis – Upload de ficheros con Ajax, File Api y Progress Api

¡Buenas! En el post anterior vimos el funcionamiento de File Api y como leer ficheros locales en servidor. En este post vamos a seguir usando File Api pero lo vamos a combinar con XMLHttpRequest y progress Api para ver como podemos hacer uploads de ficheros al servidor de forma fácil y asíncrona.

Para empezar vamos a montar la página:

<!DOCTYPE html>

<html>

<head>

    <meta name="viewport" content="width=device-width" />

    <title>Index</title>

</head>

<body>

    <div>

        Selecciona fichero.

        <input type="file" id="file" value="enviar" /> <br />

        <progress id="progress"></progress>

    </div>

</body>

</html>

Un simple input file y un progress para poder mostrar el progreso.

Ahora el siguiente punto es usar XMLHttpRequest para hacer la petición y enviar el fichero de forma asíncrona. Para ello nos vamos a aprovechar de la característica de que el XMLHttpRequest puede enviar un objeto File. Para ello usamos FormData que nos simplifica el código. Usando formData nos basta con una llamada a append para añadir el fichero. No solo esto, al usar FormData XMLHttpRequest usará el content-type correcto (“multipart/form-data”) al realizar la petición, sin que lo tengamos que establecer nosotros. Fijaos como després de abrir la conexión (xhr.open) nos limitamos a mandar el FormData que es quien contiene los datos 🙂

<script type="text/javascript">       

    function ficheroSeleccionado(e) {

        if (e.target.files.length > 0) {

            subirFichero(e.target.files[0]);

        }

    }

 

    function subirFichero(file) {

        var xhr = new XMLHttpRequest();

        var formData = new FormData();

        formData.append("file", file);

 

        xhr.addEventListener("error", function(e) {

            alert("Error subiendo el archivo.");

            var progress = document.getElementById("progress");

            progress.value = 0;

        }, false);

 

        xhr.addEventListener("load", function(e) {

            alert("fichero subido: " + e.target.status + "->" + e.target.statusText);

        });

 

        xhr.open(‘POST’, @Url.Action("Index"), true);

        xhr.send(formData);

    }

    document.getElementById("file").addEventListener("change", ficheroSeleccionado, false);

</script>

Nota: El objeto File se añade con el nombre “file” al FormData porque ese es el nombre del parámetro en la acción de destino del controlador (he usado ASP.NET MVC).

Con esto ya tenemos un file uploader con Ajax… ¿Qué sencillo, no? Pues, tal y como diría cierto conejo pesado, ¡no se vayan todavía, aún hay más!

Progress API

El objeto XMLHttpRequest define una propiedad llamada upload que devuelve el XMLHttpRequestUpload asociado. Pues bien dicho objeto define un evento, llamado “progress” que se va lanzando cada cierto tiempo donde nos informa del estado de la petición. Es decir, que ahora podemos saber cada cierto tiempo el total de bytes que se tienen que enviar y el total ya enviados. Y con ello podemos mostrar una progress bar (en mi caso he usado directamente un <progress>):

xhr.upload.addEventListener("progress", function(e) {

    if (e.lengthComputable) {

        var progress = document.getElementById("progress");

        progress.max = e.total;

        progress.value = e.loaded;

    }

}, false);

Y lisos, es así de sencillo! Con ello ya tenemos un file uploader, que funciona por Ajax y que además con una progress nos va mostrando como va la subida de ficheros al servidor.

¿Fácil no? 🙂

PD: Si vas a probar el código en local recuerda que .NET limita el tamaño de la petición por defecto (sobre unos 4MB creo). Si vas a probar con archivos grandes usa <httpRuntime maxRequestLength=”xxx” /> para establecer el tamaño máximo de petición.

PD2: Y recuerda que aún cuando uses httpRuntime, hay otro límite que aplica IIS (maxAllowedContentLength): http://msdn.microsoft.com/en-us/library/ms689462%28VS.90%29.aspx

Un comentario sobre “HTML5 Apis – Upload de ficheros con Ajax, File Api y Progress Api”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *