Sunday, April 8, 2012

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



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:





multipartformdata





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:





wrongcontenttype





As you can see, the content type is wrong...



Source: Tips4all

2 comments:

  1. I think you cant do it in ajax to support all the browsers, I might say good to check this ajax uploader plugin to see how they have done it http://valums.com/ajax-upload/

    ReplyDelete
  2. Here's some working code for FormData

    and the Mozilla FormData Documentation

    oh and here's one for jQuery

    Hope this helps

    ReplyDelete