Do you know why you cannot send files via $.post? Maybe you don’t event know how you should start sending files? In this post you’re going to learn how to send files via ajax requests. I’m not going to show you how to implement server-side code, it’s up to you.

Preparation

Let’s start by preparing simple HTML form:

1
2
3
4
<form enctype="multipart/form-data" action="/Upload" method="post">
    <input name="Picture" type="file">
    <button type="submit">Send!</button>
</form>

There is one point which should be noted. I’ve set the enctype attribute to multipart/form-data. It is required when you send files via regular forms, but since this will be sent via ajax it’s not needed. I’ve left it as a fallback.

Make sure that your page also includes jQuery script. We’ll also write some JavaScript code, so we need a place to put it.

If you already have server-side app ready, then you can test file upload. It works, but the files will be sent in a non-ajax way.

Ajax file upload

In it’s current state the form behaves in a regular way (post and reload). Right now we have to override submit button handler so form won’t be sent:

1
2
3
4
5
$(function() {
    $('button[type=submit]').click(function (event) {
        event.preventDefault();
    });
});

Next, we have to preparete form fields (in this case only the file) for sending. For this we’ll use FormData, which will construct a data structure representing our form fields. Big advantage of FormData is that it can be easily sent via ajax.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$(function() {
    $('button[type=submit]').click(function (event) {
        event.preventDefault();

        // retrieve form element
        var form = this.form;
        // prepare data
        var data = new FormData(form);
    });
});

In the last step we’ll send the data. For this we need to determine the url which will handle our request. We’ll take it from form action attribute. Then we set a couple of options for $.ajax.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
$(function() {
    $('button[type=submit]').click(function (event) {
        event.preventDefault();

        // retrieve form element
        var form = this.form;
        // prepare data
        var data = new FormData(form);
        // get url
        var url = form.action;

        // send request
        $.ajax({
            type: 'POST',
            url: url,
            data: data,
            processData: false,
            contentType: false
        });
    });
});

Why $.post won't work

Sometimes it happens that someone tries to send files using $.post instead of $.ajax. This won’t work and they don’t know why. Let me exaplain why.

First things first, $.post is just a shorthand method, which under the hood uses $.ajax. Basically $.post sets parameters and executes $.ajax. It makes code more readable and shorter. Here’s an example:

1
2
3
4
// when you use:
$.post(url);
// it's the same as:
$.ajax({ method: 'POST', url: url });

Secondly, it is impossible to set some of the parameters which have to be changed when using $.post (for example processData). For this reason the request uses default settings values. When you want to change them you have to use $.ajax.

Lastly, the default settings values are inappropriate for sending files.

Default value for processData setting is true.It processes the data in such a way that it will fit default content-type (application/x-www-form-urlencoded). Since we’re sending files, we don’t want that, so we set it to false.

Then we have contentType setting, which has a default value set to application/x-www-form-urlencoded; charset=UTF-8. When we set it to false content-type will be set to multipart/form-data, which is required when sending files.

Handling the request

Once the file is uploaded you’ll probably want to perform some kind of action. You can that by assigning callbacks to $.ajax using any of four available methods. Let’s see how it looks like:

1
2
3
$.ajax({ method: 'POST', url: url }).done(function () {
    // show image when upload has finished
});

A really quick summary of these four methods is as follows:

  • done() – use when the request was successfull
  • fail() – when the request was unsuccessfull
  • always() – use regardless of success or failure
  • then() – a shorthand which allows passing done and fail callbacks

For more throughout explanation of $.ajax and the callbacks listed above please refer to jQuery.ajax documentation.