Explain Codes LogoExplain Codes Logo

How to use FormData for AJAX file upload?

javascript
ajax-file-upload
formdata
javascript-objects
Alex KataevbyAlex Kataev·Dec 2, 2024
TLDR

For an AJAX file upload, initialize FormData to collect your data, add() your file, then send it all packing with XMLHttpRequest:

let formData = new FormData(); // A new hope formData.append('file', document.querySelector('#fileInput').files[0]); // The chosen one let xhr = new XMLHttpRequest(); // Our trusty droid xhr.open('POST', 'upload_url'); // Set the coordinates xhr.send(formData); // Punch it, R2!

In this simple version, replace 'upload_url' with the exact path of your server's upload endpoint. Houston, we are smooth sailing, no page reloads required.

Packing the truck: Dealing with multiple files & data types

Sometimes one is not enough. You've got a fleet of files, input fields with additional data. So let's loop:

let formData = new FormData(document.querySelector('#uploadForm')); // A bigger truck for more luggage for (let file of document.querySelector('#fileInput').files) { formData.append('files[]', file); // All aboard! } // Our stowaways. Shhh... formData.append('username', 'HanSolo'); formData.append('token', 'ChewbaccaIsMyCopilot');

Just like loading up the Millennium Falcon, every piece of cargo (file or other data type) has its place ready in the FormData object.

Supercharging our droid: Enhancing the AJAX request

$.ajax({ url: 'upload_url', type: 'POST', // Smuggler's choice data: formData, contentType: false, // Let the Wookiee win processData: false, // Trust the force, Luke beforeSend: function() { // No spoilers! Disable the button or show a spinner }, success: function(response) { // Celebratory Ewok dance! }, error: function(jqXHR, textStatus, errorThrown) { // DO or DO NOT. There is no try. Except this error. } });

Why contentType: false? It stops jQuery from declaring application/x-www-form-urlencoded to all. processData: false keeps jQuery from mulling over the FormData object.

Compatibility and progress reporting

To use the contentType: false set up, ensure jQuery 1.6 or newer. After sending R2 off, wouldn't you like to know his progress? Well, the droid can communicate it back:

xhr.upload.onprogress = function(e) { if (e.lengthComputable) { let percentage = (e.loaded / e.total) * 100; //R2-D2's secret Morse Code // Update or flash a light } }; xhr.upload.onloadstart = function(e) { // Warming up the hyperdrive }; xhr.upload.onloadend = function(e) { // The Endor party goes here };

May the network be with you

Some times traffic jams can happen in the most remote galaxies. A timeout fallback will allow the Force to be with you, always.

$.ajax({ // Usual suspects timeout: 30000, // Hold your breath for 30 seconds // Roll credits });

On timeout or network disturbance, implement a retry mechanism, or a kindly "Server is down, young Padawan."

Sith-proofing the server

The Dark Side is always there, lurking. Secure your file handling server-side by validating file types, sizes, and watches for the Imperial Walker attack (a multitude of simultaneous uploads). Always authenticate inputs, the Sith move among us.