Question

How to Upload Files Asynchronously with jQuery and FormData

javascriptjqueryajaxasynchronousxmlhttprequest

Question

I want to upload a file asynchronously using jQuery.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>

<span>File</span>
<input type="file" id="file" name="file" size="10" />
<input id="uploadbutton" type="button" value="Upload" />
$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: "multipart/form-data",
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded");
            }
        });
    });
});

Instead of uploading the actual file, only the filename is being sent. How can I correctly upload the file asynchronously with jQuery?

Short Answer

By the end of this page, you will understand why reading a file input with .val() only gives you the filename, how to send the real file using FormData, and which jQuery AJAX options are required to upload files correctly.

Concept

When working with file uploads in the browser, a file input does not expose the raw file contents through .val(). That method only returns a string representation of the selected file, usually the filename or a fake local path.

To upload the actual file, you need to access the file object from the input element:

$("#file")[0].files[0]

This gives you a File object provided by the browser. That object contains the real file data, along with metadata such as the file name, type, and size.

To send that file with AJAX, the standard approach is to use FormData. FormData creates a multipart form request in the same format a normal HTML form would use when uploading files.

With jQuery AJAX, two settings are especially important:

  • processData: false prevents jQuery from trying to turn the data into a query string.
  • contentType: false lets the browser automatically set the correct multipart/form-data boundary.

Without these, the file upload usually fails or sends the wrong payload.

This matters in real applications because asynchronous uploads are common in:

  • profile photo uploads
  • document submission forms
  • admin dashboards
  • chat apps with attachments
  • drag-and-drop upload tools

The key idea is simple: a filename is just text; a file upload requires the actual file object.

Mental Model

Think of a file input like a luggage tag.

  • .val() gives you the label on the suitcase.
  • files[0] gives you the actual suitcase.
  • FormData is the shipping box used to send the suitcase to the server.

If you only send the label, the server learns the file name but never receives the file itself.

If you put the real file into FormData, the browser can package and send it properly.

Take Quiz

Syntax and Examples

The core pattern for asynchronous file upload with jQuery is:

var file = $("#file")[0].files[0];
var formData = new FormData();
formData.append("file", file);

$.ajax({
    url: "addFile.do",
    type: "POST",
    data: formData,
    processData: false,
    contentType: false,
    success: function (response) {
        console.log("Upload successful", response);
    },
    error: function () {
        console.log("Upload failed");
    }
});

A full beginner-friendly example:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<input type="file" id="file" name="file">
<button id="uploadbutton">Upload</button>

<script>
$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var fileInput = $("#file")[0];

        if (fileInput.files.length === 0) {
            alert("Please select a file first.");
            return;
        }

        var formData = new FormData();
        formData.append("file", fileInput.files[0]);

        $.ajax({
            url: "addFile.do",
            type: "POST",
            data: formData,
            processData: false,
            contentType: false,
            success: function () {
                alert("File uploaded successfully.");
            },
            error: function () {
                alert("Upload failed.");
            }
        });
    });
});
</script>

What this example does

  • Gets the real DOM file input using $("#file")[0]
  • Checks whether the user selected a file
  • Creates a FormData object
  • Appends the selected file under the field name file
  • Sends it with $.ajax() using the correct options

The field name in formData.append("file", ...) should match what your server expects.

Step by Step Execution

Consider this example:

$("#uploadbutton").click(function () {
    var fileInput = $("#file")[0];

    if (fileInput.files.length === 0) {
        alert("Please select a file first.");
        return;
    }

    var formData = new FormData();
    formData.append("file", fileInput.files[0]);

    $.ajax({
        url: "addFile.do",
        type: "POST",
        data: formData,
        processData: false,
        contentType: false
    });
});

Here is what happens step by step:

  1. The user clicks the Upload button.
  2. $("#file")[0] gets the actual DOM element for the file input.
  3. fileInput.files is read.
    • This is a list of selected files.
    • For a single file input, the first file is files[0].
  4. The code checks fileInput.files.length === 0.
    • If no file was selected, it shows an alert and stops.
  5. new FormData() creates an empty multipart request body.
  6. formData.append("file", fileInput.files[0]) adds the file to the request.
    • The key is file.
    • The value is the actual selected file.
  7. $.ajax() sends the request.
  8. processData: false stops jQuery from converting the data into a regular query string.
  9. contentType: false tells the browser to set the correct multipart content type automatically.
  10. The server receives the uploaded file in the file field.

If you used $("#file").val() instead, step 6 would append only a string, not the file data.

Real World Use Cases

Asynchronous file uploads are used in many real applications:

  • Profile image upload

    • A user selects a new avatar and uploads it without reloading the page.
  • Document submission

    • Users attach PDFs, resumes, or invoices in a form.
  • Messaging apps

    • A file is uploaded in the background before sending a chat message.
  • Admin dashboards

    • Staff upload CSV files, product images, or reports.
  • Content management systems

    • Editors upload article images and media assets.
  • Support tools

    • Customers attach screenshots or log files to bug reports.

In all of these cases, the browser must send the actual file binary data, not just the filename.

Take Quiz

Real Codebase Usage

In real projects, developers usually wrap file uploads with a few practical patterns.

Validation before upload

Common checks include:

  • file selected or not
  • maximum file size
  • allowed file types
  • number of files allowed

Example:

var file = $("#file")[0].files[0];

if (!file) {
    alert("Choose a file.");
    return;
}

if (file.size > 2 * 1024 * 1024) {
    alert("File is too large.");
    return;
}

Guard clauses

Developers often exit early when input is invalid:

if (!file) return;

This keeps code readable.

Upload progress

Larger apps often show a progress bar using XMLHttpRequest progress events.

Error handling

Production code usually handles:

  • network failure
  • server-side validation errors
  • unsupported file types
  • authentication problems

Sending extra fields with the file

FormData can include regular form values too:

var formData = new FormData();
formData.append("file", file);
formData.append("userId", 123);
formData.append("description", "Profile photo");

Multiple file uploads

If the input allows multiple files, developers loop over the files list and append each one.

These patterns make file uploads more robust and user-friendly.

Common Mistakes

1. Using .val() instead of the file object

This is the main issue in your original code.

Broken:

var filename = $("#file").val();

data: {
    file: filename
}

Why it fails:

  • .val() returns text, not file content.
  • The server receives only the filename string.

Correct:

var file = $("#file")[0].files[0];
var formData = new FormData();
formData.append("file", file);

2. Forgetting processData: false

Broken:

$.ajax({
    url: "addFile.do",
    type: "POST",
    data: formData
});

Why it fails:

  • jQuery may try to serialize the data incorrectly.

Correct:

processData: false

3. Forgetting contentType: false

Broken:

$.ajax({
    url: "addFile.do",
    type: "POST",
    data: formData,
    processData: false
});

Why it fails:

  • The browser needs to set the multipart boundary automatically.

Correct:

contentType: false

4. Setting enctype in the AJAX options and expecting it to work

This is a common misunderstanding.

enctype: "multipart/form-data"

Why it is misleading:

  • enctype is normally used on an HTML <form> element.
  • In jQuery AJAX uploads, FormData plus contentType: false is what matters.

5. Not checking whether a file was selected

Broken:

var file = $("#file")[0].files[0];
formData.append("file", file);

If no file is selected, file is undefined.

Better:

if ($("#file")[0].files.length === 0) {
    alert("Please select a file.");
    return;
}

6. Mismatching the field name expected by the server

If the server expects upload, but you send file, the backend may not find the uploaded data.

formData.append("file", file);

Always match the backend field name exactly.

Comparisons

ApproachWhat it sendsGood for file upload?Notes
$("#file").val()Filename as textNoOnly gives the selected file name/path string
data: { file: ... }Regular form fieldsNoWorks for text values, not binary file data
FormData + files[0]Actual file contentsYesStandard browser approach
Normal HTML form submitActual file contentsYesReloads the page unless handled differently

val() vs files[0]

MethodReturnsUse case
$("#file").val()String filename/pathDisplaying the selected filename
$("#file")[0].files[0]File objectUploading the real file

Regular AJAX data vs FormData

TypeBest for
Plain object like { name: "A" }Text fields and simple values
FormDataFiles and multipart form submissions
Take Quiz

Cheat Sheet

var fileInput = $("#file")[0];
var file = fileInput.files[0];

var formData = new FormData();
formData.append("file", file);

$.ajax({
    url: "addFile.do",
    type: "POST",
    data: formData,
    processData: false,
    contentType: false,
    success: function (response) {
        console.log(response);
    },
    error: function () {
        console.log("Upload failed");
    }
});

Rules to remember

  • Use files[0], not .val(), to get the actual file.
  • Use FormData for file uploads.
  • Always set:
    • processData: false
    • contentType: false
  • Check that a file is selected before uploading.
  • Make sure the field name matches what the server expects.

Common edge cases

  • No file selected
  • File too large
  • Wrong file type
  • Backend expecting a different field name
  • Multiple files requiring a loop

FAQ

Why does $("#file").val() only return the filename?

Because .val() reads the input's text value, not the file contents. For uploads, use $("#file")[0].files[0].

Do I need FormData to upload files with jQuery AJAX?

Yes, in modern browser-based AJAX uploads, FormData is the standard way to send files.

Why do I need processData: false and contentType: false?

They prevent jQuery from transforming the request incorrectly and allow the browser to create the proper multipart request.

Can I upload multiple files with this approach?

Yes. Use a file input with multiple and loop through input.files.

Can I send text fields together with the file?

Yes. Add them to the same FormData object using additional append() calls.

Is enctype: "multipart/form-data" enough in jQuery AJAX?

No. For AJAX file uploads, FormData and the correct jQuery options are what matter.

What should the server receive?

The server should receive a multipart form request with a file field whose name matches the key used in formData.append().

Take Quiz

Mini Project

Description

Build a small asynchronous document uploader that lets a user choose a file, validates that a file was selected, and uploads it to the server without refreshing the page. This demonstrates the exact pattern used in many real applications such as profile uploads, admin tools, and support forms.

Goal

Create a working jQuery file upload flow that sends the actual file to the server using FormData.

Requirements

  1. Add a file input and an Upload button.
  2. Prevent upload if no file is selected.
  3. Use FormData to send the selected file.
  4. Send the request with jQuery $.ajax().
  5. Show a success or error message based on the result.
Take Quiz

Keep learning

Related questions

View more