Pregunta ¿Cómo puedo subir archivos de forma asíncrona?


Me gustaría subir un archivo de forma asincrónica con jQuery. Este es mi HTML:

<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

Y aquí mi Jquery código:

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded: ");
            }
        });
    });
});

En lugar de cargar el archivo, solo obtengo el nombre del archivo. ¿Qué puedo hacer para solucionar este problema?

Solución actual

Estoy usando el Plugin jQuery Form para cargar archivos


2606
2017-10-03 10:22


origen


Respuestas:


Con HTML5 puedes subir archivos con Ajax y jQuery. No solo eso, puede hacer validaciones de archivos (nombre, tamaño y tipo MIME) o manejar el evento de progreso con la etiqueta de progreso HTML5 (o un div). Recientemente tuve que hacer una carga de archivos, pero no quería usar Destello ni Iframes o plugins y después de algunas investigaciones se me ocurrió la solución.

El HTML:

<form enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>
<progress></progress>

Primero, puede hacer una validación si lo desea. Por ejemplo, en el evento onChange del archivo:

$(':file').on('change', function() {
    var file = this.files[0];
    if (file.size > 1024) {
        alert('max upload size is 1k')
    }

    // Also see .name, .type
});

Ahora el Ajax se presenta con el clic del botón:

$(':button').on('click', function() {
    $.ajax({
        // Your server script to process the upload
        url: 'upload.php',
        type: 'POST',

        // Form data
        data: new FormData($('form')[0]),

        // Tell jQuery not to process data or worry about content-type
        // You *must* include these options!
        cache: false,
        contentType: false,
        processData: false,

        // Custom XMLHttpRequest
        xhr: function() {
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload) {
                // For handling the progress of the upload
                myXhr.upload.addEventListener('progress', function(e) {
                    if (e.lengthComputable) {
                        $('progress').attr({
                            value: e.loaded,
                            max: e.total,
                        });
                    }
                } , false);
            }
            return myXhr;
        }
    });
});

Como puede ver, con HTML5 (y algo de investigación) la carga de archivos no solo es posible sino que también es muy fácil. Pruébalo con Google Chrome ya que algunos de los componentes HTML5 de los ejemplos no están disponibles en todos los navegadores.


2335
2018-01-06 13:34



Hay varios complementos listos para realizar la carga de archivos para jQuery.

Hacer este tipo de subidas no es una experiencia agradable, por lo que la gente disfruta el uso de soluciones ya hechas.

Aquí hay algunos:

Puede buscar más proyectos en NPM (usando "jquery-plugin" como palabra clave) o en Github.


334
2017-10-15 10:35



Actualización de 2017: todavía depende de los navegadores tu usos demográficos.

Algo importante de entender con el "nuevo" HTML5 file API es eso no fue soportado hasta IE 10. Si el mercado específico al que apunta tiene una preponderancia superior a la media hacia las versiones anteriores de Windows, es posible que no tenga acceso a él.

En 2017, aproximadamente el 5% de los navegadores son de IE 6, 7, 8 o 9. Si te diriges a una gran corporación (por ejemplo, esta es una herramienta B2B, o algo que estás entregando para capacitación) ese número puede dispararse. Hace solo unos meses, en 2016, traté con una compañía que usa IE8 en más del 60% de sus máquinas.

Entonces, antes de hacer nada: comprobar qué navegador tu los usuarios usan. Si no lo hace, aprenderá una lección rápida y dolorosa de por qué "funciona para mí" no es lo suficientemente bueno en un producto para un cliente.

Mi respuesta del 2008 sigue.


Sin embargo, existen métodos viables que no son JS de carga de archivos. Puedes crear un iframe en la página (que ocultas con CSS) y luego enfocar tu formulario para publicar en ese iframe. La página principal no necesita moverse.

Es una publicación "real" por lo que no es totalmente interactiva. Si necesita el estado, necesita algo del lado del servidor para procesarlo. Esto varía masivamente dependiendo de su servidor. ASP.NET tiene mejores mecanismos PHP plain falla, pero puedes usar Perl o modificaciones de Apache para evitarlo.

Si necesita múltiples cargas de archivos, es mejor hacer cada archivo de a uno por vez (para superar los límites máximos de carga de archivos). Publique el primer formulario en el iframe, supervise su progreso usando lo anterior y, cuando haya terminado, publique el segundo formulario en el iframe, y así sucesivamente.

O usa una solución Java / Flash. Son mucho más flexibles en lo que pueden hacer con sus publicaciones ...


237
2017-10-03 10:41



Recomiendo usar el Uploader bien plugin para este propósito. Tu JavaScript el código sería:

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});

105
2017-11-21 16:38



Nota: Esta respuesta no está actualizada, ahora es posible cargar archivos usando XHR.


No puedes subir archivos usando XMLHttpRequest (Ajax). Puede simular el efecto usando un iframe o Flash. El excelente Plugin jQuery Form que publica tus archivos a través de un iframe para obtener el efecto.


87
2017-10-03 10:36



Esta Plugin de jQuery de carga de archivos AJAX sube el archivo a alguna parte y pasa el respuesta a una devolución de llamada, nada más.

  • No depende de HTML específico, solo dale un <input type="file">
  • No requiere que su servidor responda de ninguna manera en particular
  • No importa cuántos archivos use, o dónde se encuentran en la página

- Use tan poco como -

$('#one-specific-file').ajaxfileupload({
  'action': '/upload.php'
});

- o tanto como -

$('input[type="file"]').ajaxfileupload({
  'action': '/upload.php',
  'params': {
    'extra': 'info'
  },
  'onComplete': function(response) {
    console.log('custom handler for file:');
    alert(JSON.stringify(response));
  },
  'onStart': function() {
    if(weWantedTo) return false; // cancels upload
  },
  'onCancel': function() {
    console.log('no file selected');
  }
});

81
2017-07-29 00:34



Concluyendo para futuros lectores.

Carga de archivos asíncrona

Con HTML5

Puedes subir archivos con jQuery utilizando el $.ajax() método si FormData y el File API son compatibles (ambas características HTML5).

También puedes enviar archivos sin FormData pero de cualquier forma la File API debe estar presente para procesar los archivos de tal manera que se puedan enviar con XMLHttpRequest (Ajax).

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.
  processData: false,
  contentType: false                    // Using FormData, no need to process data.
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

Para un JavaScript rápido y puro (no jQuery) ejemplo ver "Envío de archivos utilizando un objeto FormData".

Retroceder

Cuando HTML5 no es compatible (no File API) la única otra solución pura de JavaScript (sin Destello o cualquier otro plugin de navegador) es el iframe escondido técnica, que permite emular una solicitud asíncrona sin usar el XMLHttpRequest objeto.

Consiste en establecer un iframe como el destino de la forma con las entradas de archivo. Cuando el usuario envía se realiza una solicitud y se cargan los archivos, pero la respuesta se muestra dentro del marco flotante en lugar de volver a representar la página principal. Ocultar el iframe hace que todo el proceso sea transparente para el usuario y emula una solicitud asincrónica.

Si se hace correctamente, debería funcionar prácticamente en cualquier navegador, pero tiene algunas advertencias sobre cómo obtener la respuesta del iframe.

En este caso, es posible que prefieras usar un plugin wrapper como Bifröst que usa el técnica iframe pero también proporciona una jQuery transporte Ajax permitiendo enviar archivos con solo el $.ajax() método como este:

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  // Set the transport to use (iframe means to use Bifröst)
  // and the expected data type (json in this case).
  dataType: 'iframe json',                                
  fileInputs: $('input[type="file"]'),  // The file inputs containing the files to send.
  data: { msg: 'Some extra data you might need.'}
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

Complementos

Bifröst es solo una pequeña envoltura que agrega soporte de respaldo al método ajax de jQuery, pero muchos de los plugins mencionados anteriormente les gusta Plugin jQuery Formo jQuery File Upload incluya toda la pila de HTML5 para diferentes versiones de respaldo y algunas funciones útiles para facilitar el proceso. Dependiendo de sus necesidades y requerimientos, es posible que desee considerar una implementación simple o cualquiera de estos complementos.


75
2017-08-25 14:17



He estado usando la secuencia de comandos siguiente para subir imágenes que funcionan bien.

HTML

<input id="file" type="file" name="file"/>
<div id="response"></div>

JavaScript

jQuery('document').ready(function(){
    var input = document.getElementById("file");
    var formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    input.addEventListener("change", function (evt) {
        var i = 0, len = this.files.length, img, reader, file;

        for ( ; i < len; i++ ) {
            file = this.files[i];

            if (!!file.type.match(/image.*/)) {
                if ( window.FileReader ) {
                    reader = new FileReader();
                    reader.onloadend = function (e) {
                        //showUploadedItem(e.target.result, file.fileName);
                    };
                    reader.readAsDataURL(file);
                }

                if (formdata) {
                    formdata.append("image", file);
                    formdata.append("extra",'extra-data');
                }

                if (formdata) {
                    jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');

                    jQuery.ajax({
                        url: "upload.php",
                        type: "POST",
                        data: formdata,
                        processData: false,
                        contentType: false,
                        success: function (res) {
                         jQuery('div#response').html("Successfully uploaded");
                        }
                    });
                }
            }
            else
            {
                alert('Not a vaild image!');
            }
        }

    }, false);
});

Explicación

Yo uso la respuesta div para mostrar la animación y la respuesta de carga después de que se realiza la carga.

La mejor parte es que puede enviar datos adicionales como identificadores, etc. con el archivo cuando usa este script. Lo he mencionado extra-data como en el guion.

En el nivel de PHP esto funcionará como carga normal de archivos. los datos extra se pueden recuperar como $_POST datos.

Aquí no estás usando un complemento ni nada. Puede cambiar el código como lo desee. Usted no está codificando ciegamente aquí. Esta es la funcionalidad principal de cualquier carga de archivo jQuery. En realidad, Javascript.


57
2018-01-25 11:03



He encontrado algunas bibliotecas de carga de archivos basadas en jQuery realmente potentes. Mira esto:

  1. Plupload
  2. jQuery File Upload
  3. FineUploader

55
2018-04-08 16:43



Puedes subirlo simplemente con jQuery .ajax().

HTML:

<form id="upload-form">
    <div>
        <label for="file">File:</label>
        <input type="file" id="file" name="file" />
        <progress class="progress" value="0" max="100"></progress>
    </div>
    <hr />
    <input type="submit" value="Submit" />
</form>

CSS

.progress { display: none; }

Javascript:

$(document).ready(function(ev) {
    $("#upload-form").on('submit', (function(ev) {
        ev.preventDefault();
        $.ajax({
            xhr: function() {
                var progress = $('.progress'),
                    xhr = $.ajaxSettings.xhr();

                progress.show();

                xhr.upload.onprogress = function(ev) {
                    if (ev.lengthComputable) {
                        var percentComplete = parseInt((ev.loaded / ev.total) * 100);
                        progress.val(percentComplete);
                        if (percentComplete === 100) {
                            progress.hide().val(0);
                        }
                    }
                };

                return xhr;
            },
            url: 'upload.php',
            type: 'POST',
            data: new FormData(this),
            contentType: false,
            cache: false,
            processData: false,
            success: function(data, status, xhr) {
                // ...
            },
            error: function(xhr, status, error) {
                // ...
            }
       });
    }));
});

42
2017-08-08 02:59