Incredibly easy AJAX file uploads with FormData and XMLHttpRequest


File uploads used to be difficult to implement for developers.

Luckily, as web standards have advanced, so have file uploads. AJAX (XMLHttpRequests) now has ubiquitous browser support, and can be safely relied on to handle file uploads.

And even better, the new FormData interface allows you to easily grab all of the form’s keys/values in just a couple of lines.

In this post, you’ll learn how to use current AJAX best practices to upload files to a server.

The example below supports uploading multiple files in a single request, but the same technique can be used for single-file uploads as well.

Let’s begin!

Uploading Files to the Server with AJAX

Now that you know that the client’s browser is compatible, the first thing you need to do is to create 3 HTML elements which will serve as the actual UI for the file upload.

Note the multiple field on the input field, which allows the user to select multiple files by using the CTRL and SHIFT keys.

The ID’s will allow you to reference these elements in the next step

<form id="upload-form" action="handler.php" method="POST">
<input id="file-select-input" multiple="multiple" type="file" />
<button id="upload-button">Upload</button>

Also keep in mind here that the method and action fields for the form are actually not used if the form is sent using AJAX.

They are defined there as a fallback in case the browser is not running JavaScript and needs to submit the form in the traditional fashion.

Next, you need to create three variables that hold references to the <form>. <input>, and <button> elements in your HTML

var form = document.getElementById('upload-form');
var fileSelect = document.getElementById('file-select-input');
var uploadButton = document.getElementById('upload-button');

Then, you need to listen to the form’s onsubmit event:

form.onsubmit = function(event) {
  // Prevent a non-AJAX file upload from starting

  // Let the user know that the upload has begun
  uploadButton.innerHTML = 'Uploading...';

  // The rest of the code will go here...

Inside the event listener, you start by calling preventDefault() on the event object. This will prevent the browser from doing its default behavior which is to treat the upload as a non-AJAX file upload.

Then you update the innerHTML property on the uploadButton which allows the user to know that the files have begun to upload.

The next thing is to get the FileList from the <input> element and store this in a variable:

// Get the selected files from the input
var files = fileSelect.files;

Then you create a new FormData object .

This constructs the key/value pairs which are used in the data payload for the AJAX request:

// Create a new FormData object
var formData = new FormData();

Next, you take the files in the files array and add them to the formData object you just created.

This is also a good place to check to make sure the user is uploading the type of file you are expecting:

// Loop through each of the selected files.
for(var i = 0; i < files.length; i++){
  var file = files[i];

  // Check the file type
  if (!/image.*/.test(file.type)) {

  // Add the file to the form's data
  formData.append('myfiles[]', file,;

In the above snippet, you use the forEach function to iterate through each file in the files array.

The file’s type property will return the file’s MIME type as a string.

This is a list of common MIME types. This string is then tested against a regex, and will avoid inserting the file if it is not an image. Then the formData’s append method is used to add the file to the form.

The myfiles[] is also important in that this will be the name you will use to access the uploaded files on the server. The name can be anything you choose, and as with regular form data, you can append multiple values with the same name. The extra brackets at the end follow PHP’s naming conventions and allow you to loop through the multi-file upload on the server.

Next, you create a XMLHttpRequest object that is responsible for communicating with the server:

// Set up the request object
var xhr = new XMLHttpRequest();

Now you create a new connection to the server using the open method. This method takes 3 parameters: The HTTP method (ex: GET, POST, PUT, DELETE), the URL that will handle the request, and a boolean value which represents whether the request should be asynchronous:

// Open the connection and pass the file name'POST', 'handler.php', true);

Then, you’ll need to hook up an event listener that will run when the onload event is fired. Taking a look at the status property of the xhr object will let you know if the request was successful:

// Set up a handler for when the request finishes
xhr.onload = function () {
  uploadButton.innerHTML = 'Upload';
  if (xhr.status === 200) {
    // File(s) uploaded
    alert('File uploaded successfully');
  } else {
    alert('Something went wrong uploading the file.');

Finally, the last thing to do is actually send the request. You need to pass the formData object to the xhr’s send method:

// Send the Data.

And with that, you’ve got a full-fledged AJAX file uploader on the front end .

Reading the file from the server

Now that you’ve got the file upload handled on the front end, the next step is to read the data on the server. Depending on your backend stack, you’ll read the file as follows:

  • PHP: file_get_contents(“php://input”)

  • Rails: request.env[‘rack.input’]

  • Django: request.raw_post_data

Here are some resources to get you started on implementing the backend for your file uploader:

  • StackOverflow – jQuery AJAX file upload PHP

  • Pluralsight – Handling File Upload Using Ruby on Rails 5 API

  • Django – Django File Upload