Como subir una imagen con jQuery, Ajax y PHP

En este artículo vamos a explicar como permitir al usuario subir una imagen al servidor con jQuery, Ajax y PHP sin necesidad de recargar la página y sin utilizar plugins de terceros.

En el ejemplo en funcionamiento tenemos un formulario que contiene un imagen, el campo para seleccionar un archivo y un botón para realizar la subida. El usuario puede subir una imagen en formato png, jpg o gif. La imagen es cargada al servidor y se pre visualiza en pantalla sin recargar la página después de pulsar el botón «Subir».

¿Cómo lo conseguimos?

Hace tiempo andaba buscando un código como este que simplifique mucho el proceso, usando menos recursos y con un efecto similar. Resulta que es muy sencillo. Lo vamos a explicar utilizando el ejemplo que hemos creado para este tutorial.

Aspecto visual o diseño

La interfaz o aspecto visual es el siguiente:

Conseguido sin mucho esfuerzo gracias a la tecnología Bootstrap 4.

Código JavaScript necesario

En la cabecera o dentro de la etiqueta <head> de tu página tienes que agregar la librería jQuery y la llamada al evento:

<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<script>
$(document).ready(function() {
    $(".upload").on('click', function() {
        var formData = new FormData();
        var files = $('#image')[0].files[0];
        formData.append('file',files);
        $.ajax({
            url: 'upload.php',
            type: 'post',
            data: formData,
            contentType: false,
            processData: false,
            success: function(response) {
                if (response != 0) {
                    $(".card-img-top").attr("src", response);
                } else {
                    alert('Formato de imagen incorrecto.');
                }
            }
        });
        return false;
    });
});
</script>

El código anterior también puede estar incrustado justo antes de la etiqueta de cierre </body>.

Tan solo estamos esperando a que se haga click en el botón que contiene la clase «upload» para obtener el archivo seleccionado desde el ordenador para pasarlo al archivo «upload.php» para que pueda ser procesado en el servidor. Una vez se ha proceso la imagen en el servidor, si la respuesta es diferente de 0, el atributo src de nuestra imagen se cambiará por la respuesta. En caso contrario mostrar un alerta de error.

La clave del asunto está en la utilización de la clase FormData.

Los objetos FormData permiten compilar un conjunto de pares clave/valor para enviar mediante XMLHttpRequest. Están destinados principalmente para el envío de los datos del formulario, pero se pueden utilizar de forma independiente con el fin de transmitir los datos tecleados. Los datos transmitidos estarán en el mismo formato que usa el método submit() del formulario para enviar los datos si el tipo de codificación del formulario se establece en «multipart/form-data».

En el ejemplo estamos creando un objeto de tipo FormData para agregarle la imagen. El objeto FormData se lo pasamos al archivo PHP mediante la técnica Ajax. De esta forma, en el archivo PHP tendremos la información necesaria para procesar la imagen.

Este código también puede ser útil para subir otro tipo de archivos, tan solo realizando algunos ajustes.

Código HTML que debes añadir dentro del body de tu página

En el cuerpo o dentro de la etiqueta <body> agregamos el formulario que permite subir archivos:

<form method="post" action="#" enctype="multipart/form-data">
    <div class="card" style="width: 18rem;">
        <img class="card-img-top" src="images/default-avatar.png">
        <div class="card-body">
            <h5 class="card-title">Sube una foto</h5>
            <p class="card-text">Sube una imagen...</p>
            <div class="form-group">
                <label for="image">Nueva imagen</label>
                <input type="file" class="form-control-file" name="image" id="image">
            </div>
            <input type="button" class="btn btn-primary upload" value="Subir">
        </div>
    </div>
</form>

Se trata de un formulario simple que utiliza el atributo enctype=»multipart/form-data» para permitir la subida de archivos y se apoya de la tecnología Bootstrap para el diseño. Tan solo tenemos una imagen por defecto, el campo para seleccionar una imagen desde el ordenador y un botón que permite realizar la acción de subida al servidor.

Código PHP que se ejecuta en el servidor

El arhivo «upload.php» que usamos para procesar la imagen contiene lo siguiente:

<?php
if (($_FILES["file"]["type"] == "image/pjpeg")
    || ($_FILES["file"]["type"] == "image/jpeg")
    || ($_FILES["file"]["type"] == "image/png")
    || ($_FILES["file"]["type"] == "image/gif")) {
    if (move_uploaded_file($_FILES["file"]["tmp_name"], "images/".$_FILES['file']['name'])) {
        //more code here...
        echo "images/".$_FILES['file']['name'];
    } else {
        echo 0;
    }
} else {
    echo 0;
}

Simplemente comprobamos que el archivo que se está intentando subir sea del tipo adecuado. En este caso, solo queremos que se puedan subir imágenes .png, .jpg o .gif y, seguidamente, usamos la función move_uploaded_file() de PHP para depositar el archivo seleccionado en el lugar que deseamos. Lo guardamos con el mismo nombre de subida.

Después de esta acción se podrían hacer muchos más procesos, como por ejemplo registrar algo en la base de datos o enviar un email. Recuerda que todo esto se puede hacer sin recargar la página.

Como respuesta usamos la función echo de PHP para retornar un 0 en caso de error o la ruta del archivo subido para depositarlo en el src tal y como puedes ver en el success de la llamada Ajax.

Conclusiones

El efecto que conseguimos con este código de ejemplo se puede conseguir con infinidad de plugins de terceros que andan rondando por la Web pero, pensamos que este código puede resultar muy útil en casos extremos en los que sea necesario utilizar los menos recursos posibles para hacerlo funcionar o en casos que se necesite algo simple para permitir al usuario subir una imagen. El caso es que los plugins de terceros suelen tener infinidad de opciones que finalmente no se utilizan, lo que los hace muy complejos y grandes en tamaño para tenerlos depositados en el servidor.

Ver demo Descargar

Autor
Escrito por Jose Aguilar - Director ejecutivo y tecnológico en JA Modules. Experto programador PrestaShop y Experto programador WordPress.
Te ha servido? Valora esta entrada!
(30 votos, promedio: 5 de 5)
Comparte en las redes sociales
¿Buscas trabajo de programador?

24 respuestas a “Como subir una imagen con jQuery, Ajax y PHP”

  1. Moisés Cuevas dice:

    Hola. Me funciona muy bien el código, sin embargo, quisiera cambiarle el nombre. Estoy de acuerdo que lo puedo hacer directo en el archivo «upload.php», no obstante quiero mandar el nombre desde el primer script PHP donde se manda la foto, ya que el nombre proviene de una variable que se encuentra en el script original y lo quiero mandar a «upload.php» y usar ese nombre. Gracias de antemano.

    • Jose Aguilar dice:

      Hola,

      Para mandar el nombre al fichero upload.php quizá te pueda interesar hacerlo desde el javascript. Antes de la llamada Ajax puedes agregar una variable más como parámetro:

      formData.append(‘nombre’,’Nombre del fichero’);

      Saludos

  2. alberto dice:

    Hola
    tengo un problema, el script funciona, pero la imagen me la copia y es ilegible.
    creo que tiene que ver con que no la codifica en base64
    alguna sugerencia?
    Gracias

  3. Oscar Alvarado dice:

    buenas noches estoy haciendo un formulario, pero necesito que el programa me reconozca al cargar un archivo tipo texto (pdf, word) y me muestre un comodin que me diga que no es una imagen si no un archivo escrito.

  4. Jaime Salinas dice:

    Hay otras formas mas sencillas puedes poner mi script antes de

    $(«.imgAdd»).click(function(){
    $(this).closest(«.row»).find(‘.imgAdd’).before(‘Upload‘);
    });
    $(document).on(«click», «i.del» , function() {
    $(this).parent().remove();
    });
    $(function() {
    $(document).on(«change»,».uploadFile», function()
    {
    var uploadFile = $(this);
    var files = !!this.files ? this.files : [];
    if (!files.length || !window.FileReader) return; // no file selected, or no FileReader support

    if (/^image/.test( files[0].type)){ // only image file
    var reader = new FileReader(); // instance of the FileReader
    reader.readAsDataURL(files[0]); // read the local file

    reader.onloadend = function(){ // set image data as background of div
    //alert(uploadFile.closest(«.upimage»).find(‘.imagePreview’).length);
    uploadFile.closest(«.imgUp»).find(‘.imagePreview’).css(«background-image», «url(«+this.result+»)»);
    }
    }

    });
    });

    Agregar las clases en tu formulario: imgUp , imagePreview esas dos clases las veras en el html que sigue:

    Subir

  5. Jorge pucho cosme dice:

    Como puedo guardar una imagen desde un modal en una base de datos mysqli

  6. emi dice:

    Hola, muy bueno y claro el ejemple. Estoy utilizando tu codigo para un sistema de inventarios. Lo estoy haciendo para que lo utilizen cargando datos desde telefonos moviles. Con la camara frontal, menor calidad de imagen, la sube bien, con la camara posterior, mejor calidad, me da error de formato. En ambos casos las genera en jpg. Calculo que debe ser por el tamaño. Puede ser ese el problema? como lo puedo solucionar? Muchas gracias!!

    • Jose Aguilar dice:

      Hola,

      Si, podría ser que el tamaño sea el inconveniente ya que las fotografías que hacen los dispositivos móviles suelen ser imágenes con un tamaño en megas bastante grande para la subida a la web.

      Seguramente tu servidor está limitado a un tamaño concreto. Solicita si fuera posible ampliar ese tamaño máximo de subida.

      Saludos

  7. Miguel dice:

    Muchísimas Gracias por tu aporte, me sirvió mucho, una consulta, si quisiera restringir por tamaño de imagen, que debería hacer. Gracias de antemano.

    • Jose Aguilar dice:

      Hola,

      Si en el PHP haces un print_r($_FILES[‘file’]) podrás observar que hay un valor del array que contiene el size de la imagen. Puedes agregar una condición más para controlar el tamaño antes de guardar en el servidor.

      Saludos

  8. Nicolas dice:

    muchas gracias! despues de mirar 50 veces tu codigo…funciono el mio

  9. Miguel Pascual dice:

    Buenas noches, estoy intentando agregar a mi formulario la parte tuya de ajax y me sale el error undefined index file. Es un formulario con text, number y un file, los post los coge bien, pero el file no.
    tengo el ajax asi:

    $(«#art_button»).click(function(event){
    event.preventDefault();
    var formData = new FormData();
    var files = $(‘#imagen’)[0].files[0];
    formData.append(‘file’,files);
    $.ajax({
    url : «articulosalta.php»,
    method : «POST»,
    data : $(«form»).serialize(), formData,
    success : function(data){
    $(«#art_msg»).html(data);
    }
    })
    })
    y el fichero articulosalta.php me da de tiene que dar de alta el articulo, lo único que me falla es el campo file.

  10. mark dice:

    en la linea , como agrego valor «nombre» asi

    data: formData,{nombre:nombre}, no sale esta linea..

  11. aaron dice:

    Hola muy buenas, me encanto ,gracias por el aporte, solo un apunte, si quisiéramos cambiar el nombre de la imagen como lo haríamos, por ejemplo si en el mismo formulario envió un imput con un id único, como se lo podría aplicar a la imagen para re nombrarla antes de pasarla a la carpeta de almacenamiento.

    gracias de antemano.

    • Jose Aguilar dice:

      Hola,

      En la llamada a move_uploaded_file() tu puedes darle el nombre que quierar al archivo que se está subiendo. En el segundo parámetro específica la ruta del archivo agregando el identificador que haga falta como nombre del fichero .jpg

      Saludos

  12. luis angel dice:

    hola de que manera podria implementar un formulario con esto y que solo se guarde el nombre de la imagen y la imagen en la carpeta y se relacione seria de mucha ayuda

    • Jose Aguilar dice:

      Hola,

      En el código del ejemplo casi lo tienes listo. Solo tienes que ver la forma de guardar el nombre en el lugar que desees y lo mismo con guardar el archivo en la ruta que desees.

      Saludos

  13. Everst Morales Pérez dice:

    Muchísimas gracias, este código sin lugar a dudas perfecciona mucho cualquier sistema que trabaje o controle datos de personas y hace que el sistema sea muchos más ameno, bonito y ágil. Gracias por compartir

  14. Leonardo yoel dice:

    Andres que mejoras le arías, pudieras compartirla con nosotros?

  15. andres dice:

    lo implementare en mi pagina ya con algunas mejoras, amo este tipo de paginas ya que hacen que uno aplique mejoras en los codigos.

  16. Oscar Calle dice:

    Gracias, me ayudó bastante este post.

Deja una respuesta

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Ver más sobre