File Uploads
Last updated:
Practical patterns for selection, progress, validation, and upload outcomes users can trust.
01 — Foundation
Uploads need progress and honesty
Users should know what they selected, what is uploading, and what happened when it finishes.
File uploads are high-anxiety interactions — large files, slow networks, and silent failures make people repeat attempts or abandon tasks. Good upload UI shows selection, progress, success, and recoverable errors without hiding behind a generic spinner.
02 — Input
Accessible file selection
Start with a native file input before custom drag-and-drop chrome.
- visible label and button — not a hidden input on a div alone
- state accepted types and size limits in plain language before selection — see GOV.UK file upload
- show selected file names, sizes, and remove controls before upload starts
- drag-and-drop as enhancement — keyboard users must reach the same control
<label for="invoice-file">Invoice (PDF, max 10 MB)</label>
<input id="invoice-file" name="invoice" type="file" accept=".pdf,application/pdf" /> 03 — Progress
Progress, success, and failure
Long uploads need percentage or stage text — not an endless spinner.
- progress bar or status text for uploads users will wait on
- disable duplicate submits while uploading — see Async Actions
- specific errors — “File too large”, “Unsupported type”, “Upload timed out”
- allow retry without forcing users to re-select unless the file was rejected
04 — Safety
Validation and security basics
Client checks help UX; server validation is non-negotiable.
- validate type and size on the server — never trust the browser alone
- virus scanning and storage policies belong in backend docs — UI sets expectations
- multiple files — show per-file status; one failure should not erase others silently
05 — Review
Before you approve
A short checklist for file uploads in code review.
- labelled input, clear constraints, and visible selected files
- progress and outcomes are specific; retry is obvious on failure
- drag-and-drop does not replace keyboard access