How to add file upload to an HTML form
File uploads are essential for job application forms, document submission, support tickets with attachments, and any workflow where users need to send files alongside their form data.
This guide covers everything needed to add file upload to an HTML form, from basic markup to secure handling.
Basic file upload form
Two requirements for file uploads:
- The form must have
enctype="multipart/form-data" - The form must contain an
<input type="file">element
<form action="https://api.formsfort.com/submit" method="POST" enctype="multipart/form-data"> <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<label for="name">Name</label> <input type="text" id="name" name="name" required />
<label for="resume">Resume</label> <input type="file" id="resume" name="resume" />
<button type="submit">Submit application</button></form>Without enctype="multipart/form-data", the browser sends the form as application/x-www-form-urlencoded and the file data is not included. This is the most common mistake.
Restricting file types
Use the accept attribute to limit which files the user can select:
<input type="file" name="document" accept=".pdf,.doc,.docx" /><input type="file" name="photo" accept="image/*" /><input type="file" name="spreadsheet" accept=".csv,.xlsx,.xls" />| Accept value | Allows |
|---|---|
.pdf | PDF files only |
.pdf,.doc,.docx | PDF and Word documents |
image/* | All image types |
image/png,image/jpeg | PNG and JPEG only |
video/* | All video types |
audio/* | All audio types |
.csv,.xlsx | Spreadsheets |
The accept attribute only filters the file picker dialog. Users can still bypass it by selecting “All files.” Always validate file types on the server side.
Multiple file uploads
Add the multiple attribute to allow selecting more than one file:
<label for="attachments">Attachments (up to 5 files)</label><input type="file" id="attachments" name="attachments" multiple accept=".pdf,.png,.jpg" />The files are submitted as an array under the same field name. Your form backend should handle multiple files per field.
Setting file size limits
Client-side hint
Add a hidden MAX_FILE_SIZE field as a hint to the browser (not enforced by all browsers):
<input type="hidden" name="MAX_FILE_SIZE" value="10485760" /> <input type="file" name="document" />The value is in bytes (10485760 = 10MB).
Client-side validation with JavaScript
For reliable client-side size checking:
document.querySelector('input[type="file"]').addEventListener("change", (e) => { const maxSize = 10 * 1024 * 1024; for (const file of e.target.files) { if (file.size > maxSize) { alert(`${file.name} is too large. Maximum size is 10MB.`); e.target.value = ""; return; } }});Server-side enforcement
Always enforce file size limits on the server or form backend. Client-side checks can be bypassed.
Styling the file input
The default file input looks different across browsers. For a consistent appearance, hide the native input and use a custom button:
<label class="file-upload-btn"> <input type="file" name="document" hidden /> Choose file</label><span id="fileName">No file selected</span>
<script> document.querySelector('input[type="file"]').addEventListener("change", (e) => { const name = e.target.files[0]?.name ?? "No file selected"; document.getElementById("fileName").textContent = name; });</script>.file-upload-btn { display: inline-flex; align-items: center; padding: 10px 20px; background: #059669; color: white; border-radius: 8px; cursor: pointer; font-weight: 600;}.file-upload-btn:hover { background: #047857;}Drag and drop file upload
For a modern upload experience, add drag-and-drop support:
<div id="dropZone" class="drop-zone"> <p>Drag files here or click to browse</p> <input type="file" name="document" id="fileInput" hidden /></div>
<script> const dropZone = document.getElementById("dropZone"); const fileInput = document.getElementById("fileInput");
dropZone.addEventListener("click", () => fileInput.click());
dropZone.addEventListener("dragover", (e) => { e.preventDefault(); dropZone.classList.add("dragover"); });
dropZone.addEventListener("dragleave", () => { dropZone.classList.remove("dragover"); });
dropZone.addEventListener("drop", (e) => { e.preventDefault(); dropZone.classList.remove("dragover"); fileInput.files = e.dataTransfer.files; });</script>Secure file upload handling
File uploads introduce security risks. Follow these practices:
Validate MIME types server-side
Do not trust the file extension or the Content-Type header sent by the browser. Check the actual file content (magic bytes) on the server.
Scan for malware
Uploaded files can contain malware. Use a form backend that scans files before storing them.
Limit file sizes
Set maximum file size limits to prevent denial-of-service attacks through large uploads.
Restrict allowed types
Only accept the file types your form actually needs. Do not allow executable files (.exe, .sh, .bat).
Store files securely
Store uploaded files outside the web root or in cloud storage with signed URLs. Never serve uploaded files directly from a public directory.
AJAX file upload with progress
For a better user experience, upload files via AJAX with a progress indicator:
document.querySelector("form").addEventListener("submit", async (e) => { e.preventDefault(); const form = e.target; const formData = new FormData(form);
const xhr = new XMLHttpRequest(); xhr.open("POST", form.action);
xhr.upload.addEventListener("progress", (e) => { if (e.lengthComputable) { const percent = Math.round((e.loaded / e.total) * 100); document.getElementById("progress").textContent = `${percent}%`; } });
xhr.addEventListener("load", () => { if (xhr.status === 200) { document.getElementById("status").textContent = "Upload complete."; } else { document.getElementById("status").textContent = "Upload failed."; } });
xhr.send(formData);});Summary
To add file upload to an HTML form, set enctype="multipart/form-data" on the form element and add an <input type="file"> with appropriate accept restrictions. Validate file types and sizes on both the client and server side. Use a form backend service that supports file uploads, MIME validation, and malware scanning for secure handling.
Frequently asked questions
How do I add a file upload field to an HTML form?
Set the form enctype attribute to multipart/form-data and add an input element with type='file'. The form backend must support receiving multipart submissions.
Why does my file upload not work?
The most common cause is a missing enctype='multipart/form-data' attribute on the form element. Without it, the browser sends the form as URL-encoded data and the file is not included.
How do I restrict file types in an HTML form?
Use the accept attribute on the file input to restrict the file picker to specific MIME types or extensions. For example, accept='.pdf,.doc' or accept='image/*'. Always validate file types on the server side as well.
What is the maximum file size for HTML form uploads?
HTML itself does not limit file size. The limit is set by the server or form backend service. Most services allow 10-25MB per file on standard plans. Use a hidden MAX_FILE_SIZE field as a client-side hint, but always enforce limits server-side.
Can I upload multiple files in one HTML form?
Yes. Add the multiple attribute to the file input element. The browser allows selecting multiple files, and they are submitted as an array under the same field name.
Get started free
Ready to add forms to your static site?
No backend required. Point your HTML form at FormsFort and start receiving submissions in minutes.