File uploads
🏠The everyday picture
A post office accepts parcels, but checks the size and weight, refuses some contents, and gives each parcel its own tracking number rather than using whatever the sender wrote on it.
📘What it really is
- Uploads arrive as multipart form data. A library like multer reads them in Express:
const upload = multer({
storage: multer.memoryStorage(),
limits: { fileSize: 5 * 1024 * 1024, files: 1 }, // 5 MB
});
enquiriesRouter.post("/:id/attachments", requireAuth, upload.single("file"), async (req, res) => { ... });
- Where to keep uploaded files:
- on the server's disk: simple, but lost when servers are replaced and hard to share between servers;
- in object storage (Amazon S3, Cloudflare R2, Google Cloud Storage, Supabase Storage): durable, cheap, designed for files. Store the file there and its details (id, name, size, type, owner) in your database.
-
Large files can go directly from the browser to object storage using a pre-signed URL the server creates, so they don't pass through your server at all.
-
Serve private files only after checking the person is allowed to see them, or through short-lived signed links.
🖱️Try it
Add an attachment upload route for enquiries using multer with a 5 MB limit. Save each file to an uploads/ folder
(in .gitignore) under a new random id, never the original name, and store the original name, size and type in the
enquiry's data. Add a download route that checks the person is signed in.
✅Quick check
Why save an uploaded file under a random id instead of its original name?
Show the answer
Original names can clash, contain dangerous characters or ../, and reveal information.
Why do many apps keep uploads in object storage rather than on the server's disk?
Show the answer
It's durable and shared, while a server's disk can be lost or isn't shared between servers.
