Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending multipart/formdata with jQuery.ajax

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 serverside 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);     } }); 
like image 755
zoku Avatar asked Mar 22 '11 13:03

zoku


People also ask

How can add multiple form data using jQuery Ajax?

For Sending or inserting or saving multiple data in single click then you have to use Jquery and javascript code. By using Jquery or Javascript code you can generate dynamic HTML field in your HTML form. We can generate any dynamic HTML field by using Jquery and append into your form fields.

How do you send a file using multipart form data?

Follow this rules when creating a multipart form: Specify enctype="multipart/form-data" attribute on a form tag. Add a name attribute to a single input type="file" tag. DO NOT add a name attribute to any other input, select or textarea tags.

What is processData in Ajax?

processData. If set to false it stops jQuery processing any of the data. In other words if processData is false jQuery simply sends whatever you specify as data in an Ajax request without any attempt to modify it by encoding as a query string.

What is content-type false in Ajax?

contentType option to false is used for multipart/form-data forms that pass files. When one sets the contentType option to false , it forces jQuery not to add a Content-Type header, otherwise, the boundary string will be missing from it.


1 Answers

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.

like image 73
Raphael Schweikert Avatar answered Sep 18 '22 14:09

Raphael Schweikert