Sending multipart/formdata with jQuery.ajax
ajax, file-upload, form-data, jquery, multipartform-data
Solution
Starting with Safari 5/Firefox 4, it’s easiest to use the `FormData` class:
var data = new FormData();
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file-'+i, file);
});
So now you have a `FormData` object, ready to be sent along with the 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);
}
});
It’s imperative that you set the `contentType` option to `false`, forcing jQuery not to add a `Content-Type` header for you, otherwise, the boundary string will be missing from it. Also, you must leave the `processData` flag set to false, otherwise, jQuery will try to convert your `FormData` into a string, which will fail.
You may now retrieve the file in PHP using:
$_FILES['file-0']
(There is only one file, `file-0`, unless you specified the `multiple` attribute on your file input, in which case, the numbers will increment with each file.)
Using the FormData emulation for older browsers
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);
Create FormData from an existing form
Instead of manually iterating the files, the FormData object can also be created with the contents of an existing form object:
var data = new FormData(jQuery('form')[0]);
Use a PHP native array instead of a counter
Just name your file elements the same and end the name in brackets:
jQuery.each(jQuery('#file')[0].files, function(i, file) {
data.append('file[]', file);
});
`$_FILES['file']` will then be an array containing the file upload fields for every file uploaded. I actually recommend this over my initial solution as it’s simpler to iterate over.
Problem
I've got a problem sending a file to a serverside PHP-script using jQuery's ajax function. It's possible to get the File-List with `$('#fileinput').attr('files')` but how is it possible to send this Data to the server? The resulting array (`$_POST`) on the server side php-script is 0 (`NULL`) when using the file-input. I know it is possible (though I didn't find any jQuery solutions until now, only Prototye code (http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html)). This seems to be relatively new, so please do not mention file upload would be impossible via XHR/Ajax, because it's definitely working. I need the functionality in Safari 5, FF and Chrome would be nice but are not essential. My code for now is: ``` $.ajax({ url: 'php/upload.php', data: $('#file').attr('files'), cache: false, contentType: 'multipart/form-data', processData: false, type: 'POST', success: function(data){ alert(data); } }); ```