How to upload a file using the Fetch API
Last updated: August 24, 2022.
When using Fetch API to upload a file (or files) to a server, you have two options: to store the file in a formData
object or as a standalone file.
In case you are unfamiliar with making POST or PUT requests with the Fetch API, you may want to review our guide to using Fetch before proceeding with this tutorial.
Table of contents
Uploading a file stored in a FormData
object
This is the most common way to upload a file using Fetch.
First, you need to create a form with an <input>
element of type file
. Make sure a <button>
element of type submit
is also included:
<form id="form"> <input type="file" id="file"></input> <button type="submit">Upload file</button> </form>
Now, you can handle the submission of the form using the code below.
Note how the file is appended to a FormData
object before it is posted using Fetch. The append format is payload.append('key', payload, 'filename.ext')
. The third argument is optional.
By appending to a FormData
object, the payload is sent as it would be in a HTML form in which the encoding type is set to multipart/form-data
. This means no content-type
property has to be set in the configuration object passed into Fetch. It will be set automatically.
/* Sending a file appended to a FormData object */ const form = document.getElementById('form'); form.addEventListener('submit', function(event) { // Prevent default HTML page refresh event.preventDefault(); // Select file upload element const uploadElement = document.getElementById('file'); // Extract the file (for a single file, always 0 in the list) const file = uploadElement.files[0]; // Create new formData object then append file const payload = new FormData(); payload.append('CV', file, 'CV.pdf'); // POST/PUT with Fetch API fetch('https://httpbin.org/post', { method: "POST", // or "PUT" body: payload, // No content-type! With FormData obect, Fetch API sets this automatically. // Doing so manually can lead to an error }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => console.log(err)) });
Sending as part of a larger form
If your form has other input, you need to append it to the FormData
object as well.
For example:
/* Appending file and user input to the payload */ const payload = new FormData(); payload.append('CV', file, 'CV.pdf'); payload.append('First name', document.getElementById('firstName').value); payload.append('Last name', document.getElementById('lastName').value);
Viewing the contents of a FormData
object
As the FormData
object is a special type, you cannot view is contents by logging it to the console.
Data is stored in key-values pairs. So you can view the contents by iterating through it with a loop and logging each key and value to the console:
/* Extracting data from a FormData object */ for (let item of payload.entries()) { console.log(item[0]+ ', ' + item[1]); }
Allowing multiple files for single input
To allow the user send multiple files in one upload, add the multiple
attribute to an <input>
element in your HTML.
Note that when using this method, the user must select multiple files when browsing their system.
For example:
<input type="file" id="file" multiple></input>
Then, inside the function that submits the form, insert a check for the length of the files selected by the user. If the length is greater than your maximum, return a value to stop the function executing and prevent form submission:
/* A check on the number of files */ if (uploadElement.files.length) { alert("You can only upload a maximum of 2 files"); return false; }
Uploading a file without appending to FormData
Appending to a FormData
object is standard practice, but you don’t need to do so.
Without using a form at all, your HTML can be as simple as this:
<input type="file" id="file"></input> <button id="submit">Upload file</button>
The disadvantage is that you then have to set the Content-Type
header manually:
/* Uploading a file without appending to FormData */ const btn = document.getElementById('submit'); btn .addEventListener('click', function(event) { const uploadElement = document.getElementById('file'); const payload = uploadElement.files[0]; // POST with Fetch fetch('https://httpbin.org/post', { method: "POST", body: payload, headers: { 'Content-Type': "image/png" }, }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => console.log(err)) });
Related links
- httpbin.org: A simple HTTP request and response service for developers
- MDN Web Docs: Web APIs > FormData
- OpenJavaScript: Using fetch to make GET, POST, PUT and DELETE requests
- OpenJavaScript: Make fetch GET, POST, PUT and DELETE requests in a single line
- OpenJavaScript: POST form data using JavaScript’s Fetch API