When JSON Isn't Enough
Sometimes you need to send an entire HTML form — or even an image or file upload — not just JSON. For this, use FormData.
// Read all fields from an existing form automatically
const form = document.querySelector('#upload-form');
const formData = new FormData(form);
// Add extra fields programmatically
formData.append('uploadedAt', new Date().toISOString());
formData.append('category', 'profile-photo');
const response = await fetch('/api/upload', {
method: 'POST',
body: formData // DO NOT set Content-Type manually!
});
const result = await response.json();
console.log('File uploaded:', result.url);
File Upload from an Input
const fileInput = document.querySelector('#avatar-input');
fileInput.addEventListener('change', async () => {
const file = fileInput.files[0];
const formData = new FormData();
formData.append('avatar', file);
formData.append('userId', '42');
await fetch('/api/upload-avatar', { method: 'POST', body: formData });
});
Key Rules
- DO NOT manually set
Content-Type: multipart/form-data. The browser must auto-generate it with the correctboundaryseparator — if you set it manually, the server cannot parse the body. - FormData is the ONLY standard way to send
FileandBlobobjects to a server.
Caution
If you manually set the Content-Type header for FormData in fetch, the request will almost certainly break on the server. Trust the browser!