Skip to content

Submit file input via AJAX with jQuery the easy way

How to upload a file with form file input using FormData API and jQuery.

Let’s assume that you have a webform and you would like to submit it with AJAX. jQuery makes this easy so there’s no problem – you can use jQuery serialize to encode the form data, and all is well.

But then you want to include a file input field with the form submission and your remote AJAX handler doesn’t receive it at all. Well, serialize() says that it doesn’t serialize form data so now what?

The answer is the FormData object. The FormData object lets you compile a set of key/value pairs (including File input) to send using a jQuery AJAX call and the transmitted data is in the same format that the form’s submit method would use to send the data if the form’s encoding type were set to multipart/form-data.

And now to tie things together, an example of submitting an AJAX webform with jQuery. Note how the FormData object is used to “serialize” the form and how jQuery is set to not process the data and not set the content type.

$( '#my-form' )
  .submit( function( e ) {
    $.ajax( {
      url: '',
      type: 'POST',
      data: new FormData( this ),
      processData: false,
      contentType: false
    } );
  } );

Also read Uploading large files with AJAX and jQuery using FileReader API, another practical example on Planetjon.

35 thoughts on “Submit file input via AJAX with jQuery the easy way

  1. I have tried to do same but it did not work for me, $_POST & $_FILES both are empty on script page. Please help me to solve this it is very urgent.
    Here is my code :

    ajax :

    //data = $(“#reply-form”).serialize();

    data = new FormData($(“#reply-form”));


    ‘url’ : “{{URL::route(‘addEmailRequest’)}}”,

    ‘type’ : ‘post’,

    ‘data’ : data,

    processData: false,

    contentType: false,

    beforeSend: function(XHR){




  2. I have got the solution for that…………
    Just change

    data = new FormData($(“form-id”));


    data = new FormData($(“form-id”)[0]);

  3. Thank you. This is nice.
    However the code throws error at data = new FormData($(“form-id”)[0]); when you have “use strict”; set.

  4. I am tearing my hair out on this one. I have tried seven ways to Sunday to get this working on a project I am on and finally broke it into a simple test, which failed. The Ajax is called, but the PHP seems to receive empty POST data. I tried dumping the POST data with print_r and it comes up empty. My JQuery looks like:

    $( ‘#newsForm’ )

    .submit( function( e ) {

    var myData = new FormData($(“#newsForm”)[0]);

    if (!(“FormData” in window)) {

    console.log(‘FormData not supported.’);


    $.ajax( {

    url: ‘ajaxEditNewsItem.php’,

    type: ‘POST’,

    data: myData,

    cache: false,

    processData: false,

    contentType: ‘undefined’

    } );


    } );

    My HTML looks like:



    Any ideas?

      • That should be empty since I don’t have a file element. I had one in my original form, but simplified it to a 1-input form without a file to see if it would work for the simplest scenario and it bombed.

    • I’ve just noticed that in your simplified test your input field doesn’t have a name attribute. I don’t know if the HTTP spec says to ommit those fields from the request altogether (it might be available as raw data) but without a name I’m certain that it won’t show up in the $_POST variable. You need name as the data key.

      • Thanks! I added in the name attribute and now see the elements coming up in the request payload(in Chrome). I still get nothing form $_POST at the other end, though. print_r($_POST) dumps an empty array. I remember in the past when doing POST that I had to set the content-type, but we’re supposed to make it false, correct?

        • Well in the request headers, what does Chrome say that the request type is? Without a file payload or an explicit type, it might default to GET. If you send a file however, it will certainly be POST as you can’t send multipart data via GET as far as I know.

          • Request type is POST and it gets a 200 status back. Some other info back:
            Mon, 25 May 2015 19:35:14 GMT
            timeout=5, max=72
            gzip, deflate
            Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36

            The request payload(I added another variable called daysbefore) looks like:
            Content-Disposition: form-data; name=”daysbefore”

            Content-Disposition: form-data; name=”daysafter”


          • Hold the phone! Your suggestion of adding the name attribute solved the problem. I had tweaked one other thing in searching for an answer and hadn’t un-tweaked it when I added in the name attrib. After returning that to the way it had been, all is working. Thank you!

  5. where is the wrong thing it’s 3 hours trying to fix the problem and your solution is the most close one

    $( “#orders” ).submit(function( event ) {
    /* alert( “Handler for .submit() called.” );*/

    /*$.ajax( {
    data: new FormData( this ),
    processData: false,
    contentType: false
    } );*/

    var url = $(this).attr(‘action’);
    // var postData = $(this).serialize();
    var postData = new FormData( this );

    $.post(url, postData, function(o){
    if (o.result == 1) {
    var output = ‘Order Added Successfuly‘;
    } else {
    var output = ”;
    for (var key in o.error) {
    var value = o.error[key];
    output += ‘Error :‘ + value +”;
    }, ‘json’);

  6. You can upload data and files with one form using ajax.


    $(“form#data”).submit(function () {
    var formData = new FormData($(this)[0]);
    type: “POST”,
    url: base_url + ‘commencement/get_details’,
    type: ‘POST’,
    data: formData,
    success: function (response) {
    cache: false,
    contentType: false,
    processData: false

    html like: —>


Leave a Reply

Your email address will not be published. Required fields are marked *