Comunidad de diseño web y desarrollo en internet online

Cómo subir archivos con Ajax en HTML5

Sí, leíste bien, no es "ajax" disfrazado de Flash o de iFrames, es Ajax. Para lograr esto tenemos que hacer uso de varios poderosos luchadores en forma de APIs que nos ofrece HTML5 (o al menos) los navegadores más actualizados.

Antes que nada me gustaría ofrecer una breve introducción a la tercia ganadora que hará que esto sea posible.

1.- El objeto FormData


Según la MDN el objeto FormData nos permite compilar un conjunto de datos de forma clave/valor para ser enviados vía XHR "Super Saiyajin" o XHR Nivel 2. Estos datos son enviados como cualquier otro, o también usando el método .$ajax({}) de jQuery.

2.- El objeto FileReader


Por medio de este objeto podremos mostrar la imagen subida. La referencia a FileReader también aquí

3.- XHR


Y bueno, sin esto prácticamente no tendría caso el tutorial. Es una de las mejoras en el objeto XHR. Aquí más info sobre él.

Basta de tantas introducciones y veamos cómo se desarrolla la lucha. Es poco código, y se mira feo pero representa bien lo que se quiere mostrar. Sólo necesitamos un archivo con el etiquetado, otro con el javascript y uno para recoger y guardar las imágenes en el servidor; y obvio la carpeta donde se guardarán las imágenes.

El HTML

Código :

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Test</title>
    </head>
    <body>
        <div class="content">
            <input type="file" id="images" name="images[]" />
            <button id="btnSubmit">Subir archivo</button>
            <ul id="lista-imagenes">
                
            </ul>
            <div id="response"></div>
        </div>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script src="/js/upload.js"></script>
    </body>
</html>


El javascript.

Código :

(function(){
    var input = document.getElementById('images'),
        formdata = false;
    
    function mostrarImagenSubida(source){
        var list = document.getElementById('lista-imagenes'),
            li   = document.createElement('li'),
            img  = document.createElement('img');
        
        img.src = source;
        li.appendChild(img);
        list.appendChild(li);
    }
    
    //Revisamos si el navegador soporta el objeto FormData
    if(window.FormData){
        formdata = new FormData();
        document.getElementById('btnSubmit').style.display = 'none';
    }
    
    //Aplicamos la subida de imágenes al evento change del input file
    if(input.addEventListener){
        input.addEventListener('change', function(evt){
            var i = 0, len = this.files.length, img, reader, file;
            
            document.getElementById('response').innerHTML = 'Subiendo...';
            
            //Si hay varias imágenes, las obtenemos una a una
            for( ; i < len; i++){
                file = this.files[i];
                
                //Una pequeña validación para subir imágenes
                if(!!file.type.match(/image.*/)){
                    //Si el navegador soporta el objeto FileReader
                    if(window.FileReader){
                        reader = new FileReader();
                        //Llamamos a este evento cuando la lectura del archivo es completa
                        //Después agregamos la imagen en una lista
                        reader.onloadend = function(e){
                            mostrarImagenSubida(e.target.result);
                        };
                        //Comienza a leer el archivo
                        //Cuando termina el evento onloadend es llamado
                        reader.readAsDataURL(file);
                    }
                    
                    //Si existe una instancia de FormData
                    if(formdata)
                        //Usamos el método append, cuyos parámetros son:
                            //name : El nombre del campo
                            //value: El valor del campo (puede ser de tipo Blob, File e incluso string)
                        formdata.append('images[]', file);
                }
            }
            
            //Por último hacemos uso del método proporcionado por jQuery para hacer la petición ajax
            //Como datos a enviar, el objeto FormData que contiene la información de las imágenes
            if(formdata){
                $.ajax({
                   url : 'php/upload.php',
                   type : 'POST',
                   data : formdata,
                   processData : false, 
                   contentType : false, 
                   success : function(res){
                       document.getElementById('response').innerHTML = res;
                   }                
                });
            }
        }, false);
    }
}());


De pasadita el php para recoger y guardar la imagen

Código :

<?php
    foreach($_FILES['images']['error'] as $key => $error){
        if($error == UPLOAD_ERR_OK){
            $name = $_FILES['images']['name'][$key];
            move_uploaded_file($_FILES['images']['tmp_name'][$key], 'uploads/' . $name);
        }
    }
    
    echo "<h2>Archivos correctamente subidos</h2>";
?>


Si quieren subir más de una imagen solo es necesario aplicar el atributo múltiple a la etiqueta input file.
Por último es cuestión de cada desarrollador agregar un "drag&dropeo", progressbar, validaciones o previas de las imágenes.

Recomendado


Me gustaría recomendar un plugin hecho en jQuery que hace todo lo del tutorial y más. Si lo tendría que comparar con un luchador, sería Mil Máscaras sin duda alguna, hace de todo y es muy personalizable además de tener una muy buena documentación, aderezado con el framework bootstrap de Twitter, una joyita.

Espero que les haya gustado mi primer tutorial y para aclarar algunas cosas que creo se han dado en el foro. El Semántico no es una persona, es un personaje y creo debe tomarse como tal, la cuestión es divertirse y tomar gracia de todo.

Gracias :)

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate