In short
Profile photos, resumes, assignment PDFs. Almost every app needs uploads at some point, and doing it well means checking files and showing progress before anything hits the server.
Sending files from the browser to a server — typically via `FormData` and a `multipart/form-data` request, often with progress tracking.

Think of it like this
Sending a parcel at the post office
The clerk weighs your parcel, checks nothing banned is inside, then gives you a receipt with a tracking number. A good upload does the same: check size and type, send it, show progress, and get back a URL as the receipt.
Watch it happen
A photo's trip from picker to server
1/6The user picks campus.png from the file dialog. You get a File object.
The big ideas
What you need to know
input type="file"
The browser gives you File objects with a name, size in bytes and MIME type like image/png.
Check before sending
Reject files that are too big or the wrong type on the client. The server must still check again.
Preview locally
URL.createObjectURL(file) gives a temporary URL so you can show the image before uploading.
Direct-to-storage uploads
For big files, many apps get a signed URL from their server and upload straight to cloud storage like S3.
See it in code
Walk through the code
1const MAX = 2 * 1024 * 1024; // 2 MB2 3function onPick(e: React.ChangeEvent<HTMLInputElement>) {4 const file = e.target.files?.[0];5 if (!file) return;6 if (!file.type.startsWith("image/")) return setError("Please pick an image.");7 if (file.size > MAX) return setError("Max size is 2 MB.");8 9 setPreview(URL.createObjectURL(file));10 setFile(file);11}12 13<input type="file" accept="image/*" onChange={onPick} />1/42 MB written in bytes, since file.size is in bytes.
accept filters the file picker, but users can still choose other files, so check type and size in code too.
Save yourself the pain
Common mistakes
Oops
Trusting accept="image/*" to block every non-image file.
Do this instead
It's only a hint for the picker. Check file.type in code, and validate again on the server.
Oops
Creating object URLs for previews and never freeing them.
Do this instead
Call URL.revokeObjectURL(url) when the preview is replaced or the component unmounts.
Your mission
Avatar picker
Quick check
Is checking file size in the browser enough to protect your server?
Go deeper
- 1Build a file input that uploads to a real or mock endpoint using `FormData`.
- 2Add an upload progress bar using Axios's `onUploadProgress`.
- 3Validate file type/size on the client before attempting the upload.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.