File uploads use FormData with multipart/form-data encoding.
You can upload single files, multiple files, or files with additional form fields.
For progress tracking, you need to use XMLHttpRequest since
the Fetch API doesn't support upload progress (only download).
Basic File Upload with fetch()
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
const formData = new FormData();
formData.append('file', file);
formData.append('description', 'My uploaded file');
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
const result = await response.json();
console.log('Upload complete:', result);
const files = fileInput.files;
const formData = new FormData();
for (const file of files) {
formData.append('files', file);
}
Upload with Progress (XMLHttpRequest)
function uploadWithProgress(file, url, onProgress) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('file', file);
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable) {
const percent = (e.loaded / e.total) * 100;
onProgress(percent);
}
});
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(new Error(`HTTP ${xhr.status}`));
}
});
xhr.addEventListener('error', () => {
reject(new Error('Network error'));
});
xhr.addEventListener('abort', () => {
reject(new Error('Upload cancelled'));
});
xhr.open('POST', url);
xhr.send(formData);
});
}
try {
const result = await uploadWithProgress(
file,
'/api/upload',
(percent) => {
progressBar.style.width = `${percent}%`;
}
);
console.log('Uploaded:', result);
} catch (error) {
console.error('Upload failed:', error);
}
File Validation
function validateFile(file, options = {}) {
const {
maxSize = 5 * 1024 * 1024,
allowedTypes = [],
allowedExtensions = []
} = options;
const errors = [];
if (file.size > maxSize) {
const maxMB = (maxSize / 1024 / 1024).toFixed(1);
errors.push(`File too large. Max size: ${maxMB}MB`);
}
if (allowedTypes.length && !allowedTypes.includes(file.type)) {
errors.push(`Invalid file type: ${file.type}`);
}
if (allowedExtensions.length) {
const ext = file.name.split('.').pop().toLowerCase();
if (!allowedExtensions.includes(ext)) {
errors.push(`Invalid extension: .${ext}`);
}
}
return { valid: errors.length === 0, errors };
}
const validation = validateFile(file, {
maxSize: 10 * 1024 * 1024,
allowedTypes: ['image/jpeg', 'image/png', 'image/gif'],
allowedExtensions: ['jpg', 'jpeg', 'png', 'gif']
});
if (!validation.valid) {
alert(validation.errors.join('\n'));
return;
}
Try It Live
Select a file to see what would be uploaded
← Back to HTTP Examples