Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to upload a file with fetch

Short answer

Take the file from an input field, put it into FormData and send it as the body:

<input type="file" id="avatar">
<script>
  document.getElementById('avatar').addEventListener('change', async (event) => {
    const file = event.target.files[0];
    const data = new FormData();
    data.append('avatar', file);
 
    const response = await fetch('/api/avatar', { method: 'POST', body: data });
    console.log(response.status);
  });
</script>

Several files and fields

Add each file under the same name, and ordinary fields next to them:

const data = new FormData();
for (const file of input.files) {
  data.append('photos', file);
}
data.append('album', 'Summer 2025');
 
await fetch('/api/photos', { method: 'POST', body: data });

Checking before upload

Check the size and type in the browser to save the user time. The server must still check them again:

const maxSize = 2 * 1024 * 1024;
const allowed = ['image/png', 'image/jpeg'];
 
if (!allowed.includes(file.type)) {
  showMessage('Only PNG and JPEG images');
} else if (file.size > maxSize) {
  showMessage('The file is larger than 2 MB');
}

Common mistake

Do not set the Content-Type header yourself when sending FormData. The browser adds it with a special boundary string, and without it the server cannot read the file:

// wrong
await fetch('/api/avatar', {
  method: 'POST',
  headers: { 'Content-Type': 'multipart/form-data' },
  body: data,
});

Functions used in this recipe

  • fetch — Sends an HTTP request and returns a promise of the response.

Thanks for reading!

Donate to the site — we work hard for you.