Uploading Files with Fetch
Send files to a server with FormData.
Uploading Files with Fetch is a free JavaScript Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the JavaScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Uploading With fetch
To send files to a server, you POST a FormData body with fetch. The browser handles the multipart/form-data encoding for you, including file contents.
Building the FormData
Collect the file from an input and append it, along with any other fields, to a FormData object.
const file = document.querySelector('#picker').files[0];
const data = new FormData();
data.append('avatar', file);
data.append('userId', '42');
console.log(data.has('avatar'));The Basic POST
Pass the FormData as the body of a fetch POST. The response is a Promise you can await.
async function upload(data) {
const response = await fetch('/api/upload', {
method: 'POST',
body: data
});
console.log(response.status);
}Do Not Set Content-Type
A common mistake: manually setting Content-Type. Let the browser set it, because it must include the multipart boundary string. Setting it yourself breaks the upload.
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
console.log('browser added the boundary automatically');Reading the Response
Check response.ok and parse the body, often JSON, after a successful upload.
async function upload(data) {
const response = await fetch('/api/upload', { method: 'POST', body: data });
if (!response.ok) {
throw new Error('upload failed: ' + response.status);
}
const result = await response.json();
console.log(result);
}Handling Errors
Wrap the call in try/catch. Note fetch only rejects on network failures, so you must check response.ok for HTTP error statuses.
async function upload(data) {
try {
const res = await fetch('/api/upload', { method: 'POST', body: data });
if (!res.ok) throw new Error('HTTP ' + res.status);
console.log('uploaded');
} catch (err) {
console.log('error:', err.message);
}
}Uploading Multiple Files
Append several files under the same key with append, or loop over a file list to add them all.
const files = document.querySelector('#picker').files;
const data = new FormData();
for (const file of files) {
data.append('photos', file);
}
console.log(data.getAll('photos').length + ' files queued');Adding Headers Like Auth
You can add headers such as Authorization, just not Content-Type. The body stays the FormData.
const response = await fetch('/api/upload', {
method: 'POST',
headers: { Authorization: 'Bearer token123' },
body: formData
});
console.log(response.status);Sending a Generated Blob
You can upload data you create in the browser, not just picked files. Append a Blob with a filename to send a generated document.
const blob = new Blob([JSON.stringify({ ok: true })], {
type: 'application/json'
});
const data = new FormData();
data.append('report', blob, 'report.json');
await fetch('/api/upload', { method: 'POST', body: data });
console.log('generated file sent');Aborting an Upload
Use an AbortController to cancel a slow upload, for example when the user navigates away.
const controller = new AbortController();
fetch('/api/upload', {
method: 'POST',
body: formData,
signal: controller.signal
}).catch(e => console.log(e.name));
controller.abort();Why This Matters
Combining FormData with fetch is the modern, standard way to upload files: append fields and files, POST the FormData, and let the browser encode multipart with the correct boundary. Avoid setting Content-Type, always check response.ok, and clean up resources.
async function submitForm(formEl) {
const data = new FormData(formEl);
const res = await fetch('/submit', { method: 'POST', body: data });
console.log('status', res.status);
}Quick Check
Why should you NOT manually set the Content-Type header when POSTing a FormData with fetch?
Recap: Uploading Files With fetch
You learned to send files to a server:
- Append files and fields to a FormData, then pass it as the fetch
body. - Never set
Content-Typemanually; the browser adds the multipart boundary. - Check
response.okbecause fetch only rejects on network errors. - You can send multiple files, generated Blobs, and cancel uploads with
AbortController.
Frequently asked questions
Is the “Uploading Files with Fetch” lesson free?
Yes — the full text of “Uploading Files with Fetch” is free to read here on the web, and the JavaScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the JavaScript Academy course, upgrade to CoddyKit PRO.
What will I learn in “Uploading Files with Fetch”?
Send files to a server with FormData. You practise JavaScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start JavaScript Academy?
No prior experience is required. JavaScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Uploading Files with Fetch” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this JavaScript Academy lesson?
Yes. Every JavaScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The FormData Object
- Reading Files with FileReader
- Blobs and Object URLs
- Uploading Files with Fetch