File Upload in Express.js Using Multer: Node.js Backend Episode 32 (Updated June 2026)
TCS laid off 12,000 employees in July 2025, and NASSCOM-Deloitte projects that 1.25 million new AI-enabled tech jobs will open by 2027. The engineers who survive the layoffs and capture those new jobs share one thing: they build real features, not just theory. File upload is one of those features every web application needs — profile pictures, product images, resume PDFs, certificate uploads — and yet most beginners avoid it because it feels complicated. Here is the truth: with Multer middleware in Express.js, file upload takes about 15 lines of code. Episode 32 of our Node.js backend series walks you through it completely, from setting up Multer to validating file types and integrating uploads into a real Express project.
- Multer is the standard middleware for handling file uploads in Express.js — install it with npm install multer
- Multer supports two storage modes: DiskStorage (saves to server) and MemoryStorage (holds in RAM)
- File type filtering prevents users from uploading executables or unsupported formats
- The limits option controls max file size — always set this to avoid server overload attacks
- File upload skills are tested in TCS, Infosys and Wipro backend developer interviews
Why Express.js Does Not Handle File Uploads by Default
Express.js handles JSON and URL-encoded request bodies through the built-in express.json() and express.urlencoded() middleware. But when a form submits a file — encoded as multipart/form-data — Express has no built-in parser for it. The request body stays empty and req.file is undefined. This is where Multer steps in. Multer is a Node.js middleware specifically designed to parse multipart/form-data requests. It intercepts the incoming request, reads the file data from the stream, and saves it to disk or memory while making the file metadata available on the req.file object for your route handler to use. Without Multer or a similar parser, file upload simply does not work in Express.

Installing and Configuring Multer for Disk Storage
Install Multer in your Express project: npm install multer. Then at the top of your route file, require it: const multer = require("multer"). Configure DiskStorage to control where files are saved and what they are named: const storage = multer.diskStorage({ destination: function(req, file, cb) { cb(null, "uploads/") }, filename: function(req, file, cb) { cb(null, Date.now() + "-" + file.originalname) } }). Create the Multer instance: const upload = multer({ storage: storage }). The destination function tells Multer which folder to save uploads into — make sure that folder exists or Multer will throw an error. The filename function generates a unique filename by prepending a timestamp, which prevents name collisions when two users upload a file with the same original name.
Applying Multer as Express Route Middleware
Now apply the upload instance to a route. For a single file upload from a form field named "profile_pic": router.post("/upload", upload.single("profile_pic"), function(req, res) { console.log(req.file); res.json({ message: "File uploaded", filename: req.file.filename }); }). The upload.single("field_name") call tells Multer to look for a single file in the field named "profile_pic". After Multer processes the request, req.file contains: fieldname (the form field name), originalname (the file name from the client), encoding, mimetype (like "image/jpeg"), destination, filename (the saved name on disk), path (full file path), and size in bytes. For multiple file uploads, use upload.array("photos", 5) — the second argument limits the count to 5 files.

| Multer Option | What It Controls | Example Value | Why It Matters |
|---|---|---|---|
| storage.destination | Save folder path | "uploads/" | Must exist before upload |
| storage.filename | Saved file name | Date.now() + original | Prevents name collisions |
| fileFilter | Accepted file types | image/jpeg, application/pdf | Blocks executable uploads |
| limits.fileSize | Max file size in bytes | 5 * 1024 * 1024 (5MB) | Prevents server overload |
| upload.single() | Field name for file | "profile_pic" | Must match HTML input name |
File Type Filtering: Accepting Only Images and PDFs
Without file type filtering, users can upload any file — including dangerous executables or oversized videos. Add a fileFilter function to your Multer config: const upload = multer({ storage: storage, fileFilter: function(req, file, cb) { const allowedTypes = ["image/jpeg", "image/png", "image/webp", "application/pdf"]; if (allowedTypes.includes(file.mimetype)) { cb(null, true); } else { cb(new Error("Invalid file type. Only JPEG, PNG, WEBP and PDF allowed."), false); } } }). The callback cb(null, true) accepts the file; cb(new Error(...), false) rejects it. Note: always check mimetype from the server side — client-side JavaScript checks are trivially bypassed. If you are building a resume upload for a job portal or a certificate upload for a learning platform, validating mimetype server-side is a security requirement, not optional.
Setting File Size Limits and Handling Upload Errors
Set a file size limit to prevent abuse: const upload = multer({ storage: storage, limits: { fileSize: 5 * 1024 * 1024 } }). This caps uploads at 5 megabytes. When a user uploads a file that exceeds the limit, Multer throws a MulterError with code LIMIT_FILE_SIZE. Handle this in your error middleware: app.use(function(err, req, res, next) { if (err.code === "LIMIT_FILE_SIZE") { return res.status(413).json({ error: "File too large. Maximum size is 5MB." }); } next(err); }). Always wire up the error middleware after your routes — Express calls it when next(err) is invoked with an error argument. Without this handler, Multer errors crash the server response and the user sees a blank page.
Displaying Uploaded Files and Serving Static Assets
After upload, the file sits in your uploads/ folder. To let users view or download it, serve the folder as static files: app.use("/uploads", express.static("uploads")). Now a file saved as uploads/1720000000000-resume.pdf is accessible at http://localhost:3000/uploads/1720000000000-resume.pdf. Store the relative path (or full URL in production) in your database so you can retrieve it later. In production on a cloud server, store uploads in object storage like AWS S3 or Supabase Storage instead of the local filesystem — local files are lost when the server restarts or scales horizontally. The multer-s3 package extends Multer to upload directly to S3 with minimal code changes.
Full Stack Web Development Training at ABC Trainings: Pune, Sambhajinagar, Sangli
ABC Trainings runs Node.js and Full Stack Web Development training at five Maharashtra centers. Wagholi, Pune: 1st Floor, Laxmi Datta Arcade, Pune-Ahilyanagar Highway. Hadapsar, Pune: 1st Floor, Shree Tower, opposite Vaibhav Theater, Magarpatta. Cidco, Sambhajinagar: Kalpana Plaza, N-1 Cidco, opposite Eiffel Tower. Osmanpura, Sambhajinagar: near Jama Masjid, S.S.C Board road. Sangli: Shubham Emphoria, 1st Floor, Above US Polo, Sangli-Miraj Road, Vishrambag. Our Full Stack curriculum covers HTML, CSS, JavaScript, Node.js, Express, MongoDB and deployment. Weekend batches available for working IT professionals. Call 7039169629 or WhatsApp 7774002496 for batch details.
Get the AI Powered Application Development Brochure + Fees + Batch Dates on WhatsApp
Free 1:1 counselling. Placement track record. CMYKPY/PMKVY eligibility check.
💬 Get Brochure on WhatsApp📞 Call 7039169629About the author: Rahul Patil. 12 yrs experience training engineers across Maharashtra.
Visit Our Centers
- Wagholi (Pune): 1st Floor, Laxmi Datta Arcade, Pune-Ahilyanagar Highway. Call 7039169629
- Hadapsar (Pune HQ): 1st Floor, Shree Tower, opp. Vaibhav Theater, Magarpatta. Call 7039169629
- Cidco (Chh. Sambhajinagar): Kalpana Plaza, opp. Eiffel Tower, N-1 Cidco. Call 7039169629
- Osmanpura (Chh. Sambhajinagar): S.S.C Board to Peer Bazar Road, near Jama Masjid. Call 7039169629
- Sangli: Shubham Emphoria, 1st Floor, Above US Polo Assn., Sangli-Miraj Rd, Vishrambag. Weekend batches available. Call 7039169629
FAQs
What is the difference between DiskStorage and MemoryStorage in Multer?
DiskStorage saves the uploaded file to the local filesystem at the path you specify in the destination function. req.file.path gives you the saved file location. MemoryStorage keeps the file in memory as a Buffer object (available as req.file.buffer) without saving to disk — useful when you want to process the file immediately (resize an image, parse a CSV) without creating a temporary file. Use DiskStorage for production when files are stored locally, and MemoryStorage when you are streaming files directly to cloud storage like Supabase Storage or S3 without touching the local disk.
How do I upload files to Supabase Storage or AWS S3 using Multer?
For Supabase Storage, use MemoryStorage so Multer gives you req.file.buffer, then call the Supabase JavaScript client: const { data, error } = await supabase.storage.from("bucket-name").upload(filename, req.file.buffer, { contentType: req.file.mimetype }). For AWS S3, use the multer-s3 package which integrates Multer directly with S3: const upload = multer({ storage: multerS3({ s3: s3Client, bucket: "your-bucket", key: function(req, file, cb) { cb(null, Date.now() + file.originalname) } }) }). Cloud storage is the correct approach for production applications — local filesystem uploads are lost when your server restarts or scales across multiple instances.
Can I upload multiple files in a single Express.js route with Multer?
Yes. Use upload.array("field_name", maxCount) for multiple files in a single field — req.files is then an array of file objects. Use upload.fields([{ name: "avatar", maxCount: 1 }, { name: "photos", maxCount: 5 }]) for multiple named fields with different limits — req.files["avatar"] and req.files["photos"] each become arrays. Each element in the array has the same properties as req.file in the single upload case: filename, mimetype, size, path etc. Always set sensible maxCount values to prevent users from flooding your upload route with hundreds of files in a single request.
Is file upload with Multer tested in TCS, Infosys and Wipro backend developer interviews?
Yes. File upload is a standard test topic in technical interviews at TCS, Infosys, Wipro and product companies hiring Node.js backend developers. You will typically be asked to write the Multer configuration from scratch (storage, fileFilter, limits), apply it to a route, and handle errors. Some interviews extend this to asking about cloud storage integration or how you would secure the upload endpoint. ABC Trainings backend module covers all of these scenarios with hands-on project exercises so students arrive at interviews having built real upload features, not just watched tutorials.



