¿Cómo puedo subir archivos de forma asincrónica con jQuery?

Resuelto Sergio del Amo asked hace 15 años • 0 respuestas

Me gustaría subir un archivo de forma asincrónica con jQuery.

$(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: ");
            }
        });
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>
Expandir fragmento

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

Sergio del Amo avatar Oct 03 '08 17:10 Sergio del Amo
Aceptado

Con HTML5 puedes realizar cargas de archivos con Ajax y jQuery. No solo eso, puedes 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 crear un cargador de archivos, pero no quería usar Flash ni Iframes ni complementos y después de investigar un poco 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, puedes hacer alguna validación si lo deseas. Por ejemplo, en el .on('change')caso 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()envío 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 puedes ver, con HTML5 (y algunas investigaciones) cargar archivos no sólo es posible sino también muy fácil. Pruébelo con Google Chrome ya que algunos de los componentes HTML5 de los ejemplos no están disponibles en todos los navegadores.

olanod avatar Jan 06 '2012 13:01 olanod

Actualización de 2019: todavía depende de los navegadores que utilice su grupo demográfico.

Una cosa importante que hay que entender con la "nueva" API HTML5 filees que no fue compatible hasta IE 10 . Si el mercado específico al que apunta tiene una propensión mayor que el promedio hacia versiones anteriores de Windows, es posible que no tenga acceso a él.

A partir de 2017, alrededor del 5% de los navegadores son IE 6, 7, 8 o 9. Si ingresa a una gran corporación (por ejemplo, esta es una herramienta B2B o algo que está entregando para capacitación), ese número puede dispararse. En 2016, traté con una empresa que utilizaba IE8 en más del 60 % de sus máquinas.

Es 2019 en el momento de esta edición, casi 11 años después de mi respuesta inicial. IE9 y versiones inferiores rondan globalmente la marca del 1%, pero todavía hay grupos de mayor uso.

La conclusión importante de esto, cualquiera que sea la característica, es comprobar qué navegador utilizan sus usuarios . Si no lo hace, aprenderá una lección rápida y dolorosa de por qué "funciona para mí" no es lo suficientemente bueno como entregable a un cliente. caniuse es una herramienta útil, pero tenga en cuenta de dónde obtienen sus datos demográficos. Es posible que no se alineen con los suyos. Esto nunca es más cierto que en los entornos empresariales.

Mi respuesta de 2008 sigue.


Sin embargo, existen métodos viables que no son JS para cargar archivos. Puede crear un iframe en la página (que oculta con CSS) y luego orientar su formulario para publicar en ese iframe. La página principal no necesita moverse.

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

Si necesita cargar varios archivos, es mejor hacerlo cada archivo de uno en uno (para superar los límites máximos de carga de archivos). Publique el primer formulario en el iframe, supervise su progreso utilizando lo anterior y cuando haya terminado, publique el segundo formulario en el iframe, y así sucesivamente.

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

Oli avatar Oct 03 '2008 10:10 Oli

Recomiendo utilizar el complemento Fine Uploader para este propósito. Tu JavaScriptcódigo sería:

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});
 avatar Nov 21 '2008 16:11

Nota: esta respuesta está desactualizada, ahora es posible cargar archivos usando XHR.


No puede cargar archivos usando XMLHttpRequest (Ajax). Puede simular el efecto utilizando un iframe o Flash. El excelente complemento jQuery Form que publica sus archivos a través de un iframe para obtener el efecto.

Mattias avatar Oct 03 '2008 10:10 Mattias

Conclusión para futuros lectores.

Carga de archivos asincrónica

Con HTML5

Puede cargar archivos con jQuery utilizando el $.ajax()método si FormData y File API son compatibles (ambas funciones HTML5).

También puede enviar archivos sin FormData , pero de cualquier manera la API de archivos debe estar presente para procesar archivos de tal manera que puedan enviarse 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 ver un ejemplo rápido y puro de JavaScript ( sin jQuery ), consulte " Envío de archivos utilizando un objeto FormData ".

Retroceder

Cuando no se admite HTML5 (sin File API ), la única otra solución de JavaScript puro (sin Flash ni ningún otro complemento de navegador) es la técnica de iframe oculto , que permite emular una solicitud asincrónica sin utilizar el objeto XMLHttpRequest .

Consiste en establecer un iframe como destino del formulario con las entradas del archivo. Cuando el usuario envía, se realiza una solicitud y los archivos se cargan, pero la respuesta se muestra dentro del iframe en lugar de volver a mostrar 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 prefiera utilizar un complemento contenedor como Bifröst , que utiliza la técnica iframe pero también proporciona un transporte jQuery Ajax que permite enviar archivos simplemente con un $.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 un pequeño contenedor que agrega soporte de respaldo al método ajax de jQuery, pero muchos de los complementos antes mencionados, como jQuery Form Plugin o jQuery File Upload, incluyen toda la pila, desde HTML5 hasta diferentes respaldos y algunas características útiles para facilitar el proceso. Dependiendo de sus necesidades y requisitos, es posible que desee considerar una implementación básica o cualquiera de estos complementos.

404 avatar Aug 25 '2014 14:08 404