File upload through AJAX and FormData object
Introduction
The introduction of AJAX marked a huge leap forward in the history of the web. The ability to communicate with a web server without reloading the page has revolutionised how web applications are built. The primary technology that enables AJAX (XMLHttpRequests) has evolved significantly since the initial conception of dynamic websites.
With XMLHttpRequest
, file upload through AJAX is supported. E.g. through FormData
object, but unfortunately it is not supported by old browsers.
Step 1: Make a Upload form
The first thing you need to do is to build your HTML form that will allow the user to select the file(s) to upload. To keep things simple lets use a standard <input>
element with the file
type.
<form id="file-form" action="handler.php" method="POST">
<input type="file" id="file-select" name="photos[]" multiple/>
<button type="submit" id="upload-button">Upload</button>
</form>
Notice that the <input>
element includes the multiple
attribute. This will allow the user to select multiple files from the file picker launched by the browser. If you don’t specify this attribute the user can only select one file.
Now that you’ve got your HTML form set up lets take a look at the JavaScript code that will handle the file upload.
Step 2: Uplad files to the server
First of all you need to create three variables that hold references to the <form>
, <input>
, and <button>
elements in your HTML markup.
var form = document.getElementById('file-form');
var fileSelect = document.getElementById('file-select');
var uploadButton = document.getElementById('upload-button');
Next you need to attach an event listener to the form’s onsubmit
event.
form.onsubmit = function(event) {
event.preventDefault();
// Update button text.
uploadButton.innerHTML = 'Uploading...';
// The rest of the code will go here...
}
Inside the event listener you start by calling event.preventDefault()
to prevent the browser from submitting the form, allowing us to handle the file upload using AJAX instead.
Next you update the uploadButton
's innerHTML
property to Uploading....
. This just provides a bit of feedback to the user so they know the files are uploading.
Your next job is to retrieve the FileList
from the <input>
element and store this in a variable. You can do this by accessing the files
property.
// Get the selected files from the input.
var files = fileSelect.files;
You then create a new FormData
object. This is used to construct the key/value pairs which form the data payload for the AJAX request.
// Create a new FormData object.
var formData = new FormData();
Step 3: Retrieve files from input
Your next job is to loop through each of the files in the files
array and add them to the formData
object you just created. You’ll also want to check that the user has selected the type of file you’re 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 (!file.type.match('image.*')) {
continue;
}
// Add the file to the request.
formData.append('photos[]', file, file.name);
}
Here you’re first fetching the current file from the files
array and then checking to make sure it’s an image. The file’s type
property will return the file type as a string. You can therefore use the JavaScript match()
method to ensure that this string matches the desired type. If the file type does not match, you skip the file by calling continue
.
You then use the append
method on the formData
object to add this file to the data payload.
The FormData.append()
method is used to handle Files, Blobs, or Strings.
// Files
formData.append(name, file, filename);
// Blobs
formData.append(name, blob, filename);
// Strings
formData.append(name, value);
The first parameter specifies the name
of the data entry. This will form the key
in the data payload. The second parameter specifies either a File
, Blob
, or String
that will be used as the value
for the data entry. When appending a File
or Blob
you can also specify a filename
, but this isn’t required.
Step 4: Communicate with Server
Next you need to set up the XMLHttpRequest
that is responsible for communicating with the server. To do this you first need to create a new XMLHttpRequest
object.
// Set up the request.
var xhr = new XMLHttpRequest();
You now need to create a new connection to the server. You do this using the open
method. This method takes three parameters. The HTTP method
, the url
that will handle the request, and a boolean value that determines whether the request should be dealt with asynchronously.
// Open the connection.
xhr.open('POST', 'handler.php', true);
Next you need to set up an event listener that will be triggered when the onload
event is fired. Examining the status
property of the xhr
object will tell you if the request completed successfully.
// Set up a handler for when the request finishes.
xhr.onload = function () {
if (xhr.status === 200) {
// File(s) uploaded.
uploadButton.innerHTML = 'Upload';
} else {
alert('An error occurred!');
}
};
All that’s left to do now is send the request. Pass the formData
object to the send
method which is available on the xhr
object.
// Send the Data.
xhr.send(formData);
That’s everything you need to know to start uploading files using AJAX. Your server-side code will need to extract the files from the request and process them as desired.
Browser Support
Browser support for the technologies used in this post is generally good. Internet Explorer being the only exception. You will be okay with IE 10 and above, but earlier versions of IE didn’t include support for some of the XMLHttpRequest features covered in this post.
IE | Firefox | Chrome | Safari | Opera |
---|---|---|---|---|
10.0+ | 4.0+ | 7.0+ | 5+ | 12+ |
References & Resources
- http://blog.teamtreehouse.com/uploading-files-ajax
Latest Post
- Dependency injection
- Directives and Pipes
- Data binding
- HTTP Get vs. Post
- Node.js is everywhere
- MongoDB root user
- Combine JavaScript and CSS
- Inline Small JavaScript and CSS
- Minify JavaScript and CSS
- Defer Parsing of JavaScript
- Prefer Async Script Loading
- Components, Bootstrap and DOM
- What is HEAD in git?
- Show the changes in Git.
- What is AngularJS 2?
- Confidence Interval for a Population Mean
- Accuracy vs. Precision
- Sampling Distribution
- Working with the Normal Distribution
- Standardized score - Z score
- Percentile
- Evaluating the Normal Distribution
- What is Nodejs? Advantages and disadvantage?
- How do I debug Nodejs applications?
- Sync directory search using fs.readdirSync