Envío de datos multiparte/formularios con jQuery.ajax
Tengo un problema al enviar un archivo a un script PHP del lado del servidor usando la función ajax de jQuery. Es posible obtener la lista de archivos, $('#fileinput').attr('files')
pero ¿cómo es posible enviar estos datos al servidor? La matriz resultante ( $_POST
) en el script php del lado del servidor es 0 ( NULL
) cuando se utiliza la entrada del archivo.
Sé que es posible (aunque no encontré ninguna solución jQuery hasta ahora, solo código Prototye ( http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html ) ).
Esto parece ser relativamente nuevo, así que no menciones que la carga de archivos sería imposible a través de XHR/Ajax, porque definitivamente está funcionando.
Necesito la funcionalidad en Safari 5, FF y Chrome estarían bien pero no son esenciales.
Mi código por ahora es:
$.ajax({
url: 'php/upload.php',
data: $('#file').attr('files'),
cache: false,
contentType: 'multipart/form-data',
processData: false,
type: 'POST',
success: function(data){
alert(data);
}
});
A partir de Safari 5/Firefox 4, es más fácil usar la FormData
clase:
var data = new FormData();
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file-'+i, file);
});
Ahora tiene un FormData
objeto, listo para ser enviado junto con XMLHttpRequest.
jQuery.ajax({
url: 'php/upload.php',
data: data,
cache: false,
contentType: false,
processData: false,
method: 'POST',
type: 'POST', // For jQuery < 1.9
success: function(data){
alert(data);
}
});
Es imperativo que establezca la contentType
opción en false
, lo que obligará a jQuery a no agregar un Content-Type
encabezado; de lo contrario, faltará la cadena de límite. Además, debe dejar el processData
indicador establecido en falso; de lo contrario, jQuery intentará convertirlo FormData
en una cadena, lo cual fallará.
Ahora puedes recuperar el archivo en PHP usando:
$_FILES['file-0']
(Solo hay un archivo, file-0
a menos que haya especificado el multiple
atributo en la entrada de su archivo, en cuyo caso, los números se incrementarán con cada archivo).
Usando la emulación FormData para navegadores más antiguos
var opts = {
url: 'php/upload.php',
data: data,
cache: false,
contentType: false,
processData: false,
method: 'POST',
type: 'POST', // For jQuery < 1.9
success: function(data){
alert(data);
}
};
if(data.fake) {
// Make sure no text encoding stuff is done by xhr
opts.xhr = function() { var xhr = jQuery.ajaxSettings.xhr(); xhr.send = xhr.sendAsBinary; return xhr; }
opts.contentType = "multipart/form-data; boundary="+data.boundary;
opts.data = data.toString();
}
jQuery.ajax(opts);
Crear FormData a partir de un formulario existente
En lugar de iterar manualmente los archivos, el objeto FormData también se puede crear con el contenido de un objeto de formulario existente:
var data = new FormData(jQuery('form')[0]);
Utilice una matriz nativa de PHP en lugar de un contador
Simplemente nombre los elementos de su archivo de la misma manera y termine el nombre entre paréntesis:
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file[]', file);
});
$_FILES['file']
Entonces habrá una matriz que contiene los campos de carga de archivos para cada archivo cargado. De hecho, recomiendo esto en lugar de mi solución inicial, ya que es más sencillo de iterar.
Mira mi código, hace el trabajo por mí.
$( '#formId' )
.submit( function( e ) {
$.ajax( {
url: 'FormSubmitUrl',
type: 'POST',
data: new FormData( this ),
processData: false,
contentType: false
} );
e.preventDefault();
} );