How to send FormData objects with Ajax-requests in jQuery?

ajax, html, javascript, jquery, multipartform-data

Solution

I believe you could do it like this :

var fd = new FormData();    
fd.append( 'file', input.files[0] );

$.ajax({
  url: 'http://example.com/script.php',
  data: fd,
  processData: false,
  contentType: false,
  type: 'POST',
  success: function(data){
    alert(data);
  }
});

Notes:

Setting `processData` to `false` lets you prevent jQuery from automatically transforming the data into a query string. See the docs for more info.

Setting the `contentType` to `false` is imperative, since otherwise jQuery will set it incorrectly.

Problem

The XMLHttpRequest Level 2 standard (still a working draft) defines the `FormData` interface. This interface enables appending `File` objects to XHR-requests (Ajax-requests). Btw, this is a new feature - in the past, the "hidden-iframe-trick" was used (read about that in my other question). This is how it works (example): ``` var xhr = new XMLHttpRequest(), fd = new FormData(); fd.append( 'file', input.files[0] ); xhr.open( 'POST', 'http://example.com/script.php', true ); xhr.onreadystatechange = handler; xhr.send( fd ); ``` where `input` is a `<input type="file">` field, and `handler` is the success-handler for the Ajax-request. This works beautifully in all browsers (again, except IE). Now, I would like to make this functionality work with jQuery. I tried this: ``` var fd = new FormData(); fd.append( 'file', input.files[0] ); $.post( 'http://example.com/script.php', fd, handler ); ``` Unfortunately, that won't work (an "Illegal invocation" error is thrown - screenshot is here). I assume jQuery expects a simple key-value object representing form-field-names / values, and the `FormData` instance that I'm passing in is apparently incompatible. Now, since it is possible to pass a `FormData` instance into `xhr.send()`, I hope that it is also possible to make it work with jQuery. Update: I've created a "feature ticket" over at jQuery's Bug Tracker. It's here: http://bugs.jquery.com/ticket/9995 I was suggested to use an "Ajax prefilter"... Update: First, let me give a demo demonstrating what behavior I would like to achieve. HTML: ``` <form> <input type="file" id="file" name="file"> <input type="submit"> </form> ``` JavaScript: ``` $( 'form' ).submit(function ( e ) { var data, xhr; data = new FormData(); data.append( 'file', $( '#file' )[0].files[0] ); xhr = new XMLHttpRequest(); xhr.open( 'POST', 'http://hacheck.tel.fer.hr/xml.pl', true ); xhr.onreadystatechange = function ( response ) {}; xhr.send( data ); e.preventDefault(); }); ``` The above code results in this HTTP-request: This is what I need - I want that "multipart/form-data" content-type! The proposed solution would be like so: ``` $( 'form' ).submit(function ( e ) { var data; data = new FormData(); data.append( 'file', $( '#file' )[0].files[0] ); $.ajax({ url: 'http://hacheck.tel.fer.hr/xml.pl', data: data, processData: false, type: 'POST', success: function ( data ) { alert( data ); } }); e.preventDefault(); }); ``` However, this results in: As you can see, the content type is wrong...

Original source

Related problems