[jquery] 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);
    }
});

This question is related to jquery ajax file-upload multipartform-data form-data

The answer is


If your form is defined in your HTML, it is easier to pass the form into the constructor than it is to iterate and add images.

$('#my-form').submit( function(e) {
    e.preventDefault();

    var data = new FormData(this); // <-- 'this' is your form element

    $.ajax({
            url: '/my_URL/',
            data: data,
            cache: false,
            contentType: false,
            processData: false,
            type: 'POST',     
            success: function(data){
            ...

Just wanted to add a bit to Raphael's great answer. Here's how to get PHP to produce the same $_FILES, regardless of whether you use JavaScript to submit.

HTML form:

<form enctype="multipart/form-data" action="/test.php" 
method="post" class="putImages">
   <input name="media[]" type="file" multiple/>
   <input class="button" type="submit" alt="Upload" value="Upload" />
</form>

PHP produces this $_FILES, when submitted without JavaScript:

Array
(
    [media] => Array
        (
            [name] => Array
                (
                    [0] => Galata_Tower.jpg
                    [1] => 518f.jpg
                )

            [type] => Array
                (
                    [0] => image/jpeg
                    [1] => image/jpeg
                )

            [tmp_name] => Array
                (
                    [0] => /tmp/phpIQaOYo
                    [1] => /tmp/phpJQaOYo
                )

            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                )

            [size] => Array
                (
                    [0] => 258004
                    [1] => 127884
                )

        )

)

If you do progressive enhancement, using Raphael's JS to submit the files...

var data = new FormData($('input[name^="media"]'));     
jQuery.each($('input[name^="media"]')[0].files, function(i, file) {
    data.append(i, file);
});

$.ajax({
    type: ppiFormMethod,
    data: data,
    url: ppiFormActionURL,
    cache: false,
    contentType: false,
    processData: false,
    success: function(data){
        alert(data);
    }
});

... this is what PHP's $_FILES array looks like, after using that JavaScript to submit:

Array
(
    [0] => Array
        (
            [name] => Galata_Tower.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/phpAQaOYo
            [error] => 0
            [size] => 258004
        )

    [1] => Array
        (
            [name] => 518f.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/phpBQaOYo
            [error] => 0
            [size] => 127884
        )

)

That's a nice array, and actually what some people transform $_FILES into, but I find it's useful to work with the same $_FILES, regardless if JavaScript was used to submit. So, here are some minor changes to the JS:

// match anything not a [ or ]
regexp = /^[^[\]]+/;
var fileInput = $('.putImages input[type="file"]');
var fileInputName = regexp.exec( fileInput.attr('name') );

// make files available
var data = new FormData();
jQuery.each($(fileInput)[0].files, function(i, file) {
    data.append(fileInputName+'['+i+']', file);
});

(14 April 2017 edit: I removed the form element from the constructor of FormData() -- that fixed this code in Safari.)

That code does two things.

  1. Retrieves the input name attribute automatically, making the HTML more maintainable. Now, as long as form has the class putImages, everything else is taken care of automatically. That is, the input need not have any special name.
  2. The array format that normal HTML submits is recreated by the JavaScript in the data.append line. Note the brackets.

With these changes, submitting with JavaScript now produces precisely the same $_FILES array as submitting with simple HTML.


All the solutions above are looks good and elegant, but the FormData() object does not expect any parameter, but use append() after instantiate it, like what one wrote above:

formData.append(val.name, val.value);


  1. get form object by jquery-> $("#id")[0]
  2. data = new FormData($("#id")[0]);
  3. ok,data is your want

The FormData class does work, however in iOS Safari (on the iPhone at least) I wasn't able to use Raphael Schweikert's solution as is.

Mozilla Dev has a nice page on manipulating FormData objects.

So, add an empty form somewhere in your page, specifying the enctype:

<form enctype="multipart/form-data" method="post" name="fileinfo" id="fileinfo"></form>

Then, create FormData object as:

var data = new FormData($("#fileinfo"));

and proceed as in Raphael's code.


Nowadays you don't even need jQuery:) fetch API support table

let result = fetch('url', {method: 'POST', body: new FormData(document.querySelector("#form"))})

One gotcha I ran into today I think is worth pointing out related to this problem: if the url for the ajax call is redirected then the header for content-type: 'multipart/form-data' can be lost.

For example, I was posting to http://server.com/context?param=x

In the network tab of Chrome I saw the correct multipart header for this request but then a 302 redirect to http://server.com/context/?param=x (note the slash after context)

During the redirect the multipart header was lost. Ensure requests are not being redirected if these solutions are not working for you.


Older versions of IE do not support FormData ( Full browser support list for FormData is here: https://developer.mozilla.org/en-US/docs/Web/API/FormData).

Either you can use a jquery plugin (For ex, http://malsup.com/jquery/form/#code-samples ) or, you can use IFrame based solution to post multipart form data through ajax: https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript


I just built this function based on some info I read.

Use it like using .serialize(), instead just put .serializefiles();.
Working here in my tests.

//USAGE: $("#form").serializefiles();
(function($) {
$.fn.serializefiles = function() {
    var obj = $(this);
    /* ADD FILE TO PARAM AJAX */
    var formData = new FormData();
    $.each($(obj).find("input[type='file']"), function(i, tag) {
        $.each($(tag)[0].files, function(i, file) {
            formData.append(tag.name, file);
        });
    });
    var params = $(obj).serializeArray();
    $.each(params, function (i, val) {
        formData.append(val.name, val.value);
    });
    return formData;
};
})(jQuery);

Devin Venable's answer was close to what I wanted, but I wanted one that would work on multiple forms, and use the action already specified in the form so that each file would go to the right place.

I also wanted to use jQuery's on() method so I could avoid using .ready().

That got me to this: (replace formSelector with your jQuery selector)

$(document).on('submit', formSelecter, function( e ) {
        e.preventDefault();
    $.ajax( {
        url: $(this).attr('action'),
        type: 'POST',
        data: new FormData( this ),
        processData: false,
        contentType: false
    }).done(function( data ) {
        //do stuff with the data you got back.
    });

});

If the file input name indicates an array and flags multiple, and you parse the entire form with FormData, it is not necessary to iteratively append() the input files. FormData will automatically handle multiple files.

_x000D_
_x000D_
$('#submit_1').on('click', function() {_x000D_
  let data = new FormData($("#my_form")[0]);_x000D_
_x000D_
  $.ajax({_x000D_
    url: '/path/to/php_file',_x000D_
    type: 'POST',_x000D_
    data: data,_x000D_
    processData: false,_x000D_
    contentType: false,_x000D_
    success: function(r) {_x000D_
      console.log('success', r);_x000D_
    },_x000D_
    error: function(r) {_x000D_
      console.log('error', r);_x000D_
    }_x000D_
  });_x000D_
});
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>_x000D_
<form id="my_form">_x000D_
  <input type="file" name="multi_img_file[]" id="multi_img_file" accept=".gif,.jpg,.jpeg,.png,.svg" multiple="multiple" />_x000D_
  <button type="button" name="submit_1" id="submit_1">Not type='submit'</button>_x000D_
</form>
_x000D_
_x000D_
_x000D_

Note that a regular button type="button" is used, not type="submit". This shows there is no dependency on using submit to get this functionality.

The resulting $_FILES entry is like this in Chrome dev tools:

multi_img_file:
  error: (2) [0, 0]
  name: (2) ["pic1.jpg", "pic2.jpg"]
  size: (2) [1978036, 2446180]
  tmp_name: (2) ["/tmp/phphnrdPz", "/tmp/phpBrGSZN"]
  type: (2) ["image/jpeg", "image/jpeg"]

Note: There are cases where some images will upload just fine when uploaded as a single file, but they will fail when uploaded in a set of multiple files. The symptom is that PHP reports empty $_POST and $_FILES without AJAX throwing any errors. Issue occurs with Chrome 75.0.3770.100 and PHP 7.0. Only seems to happen with 1 out of several dozen images in my test set.


Look at my code, it does the job for me

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

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to ajax

Getting all files in directory with ajax Cross-Origin Read Blocking (CORB) Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource Fetch API request timeout? How do I post form data with fetch api? Ajax LARAVEL 419 POST error Laravel 5.5 ajax call 419 (unknown status) How to allow CORS in react.js? Angular 2: How to access an HTTP response body? How to post a file from a form with Axios

Examples related to file-upload

bootstrap 4 file input doesn't show the file name How to post a file from a form with Axios File Upload In Angular? How to set the max size of upload file The request was rejected because no multipart boundary was found in springboot Send multipart/form-data files with angular using $http File upload from <input type="file"> How to upload files in asp.net core? REST API - file (ie images) processing - best practices Angular - POST uploaded file

Examples related to multipartform-data

How do I set multipart in axios with react? Send FormData with other field in AngularJS Send multipart/form-data files with angular using $http How to set up a Web API controller for multipart/form-data Upload a file to Amazon S3 with NodeJS File upload along with other object in Jersey restful web service Uploading file using POST request in Node.js Angularjs how to upload multipart form data and a file? Convert JS Object to form data Posting raw image data as multipart/form-data in curl

Examples related to form-data

How to convert FormData (HTML5 object) to JSON Send FormData with other field in AngularJS Convert JS Object to form data Send FormData and String Data Together Through JQuery AJAX? How to add header data in XMLHttpRequest when using formdata? Node.js: How to send headers with form data using request module? How to inspect FormData? appending array to FormData and send via AJAX FormData.append("key", "value") is not working How to give a Blob uploaded as FormData a file name?