Handling File Uploads in Express with Multer
Handling File Uploads in Express with Multer
When building real-world backend systems, handling file uploads is unavoidable—profile pictures, documents, PDFs, etc. But unlike JSON data, file uploads require a different handling mechanism. This is where middleware like Multer becomes essential.
Why File Uploads Need Middleware
In a typical Express.js application running on Node.js, request bodies are usually parsed using middleware like express.json() or express.urlencoded().
However, file uploads are sent using a special encoding type:
👉 multipart/form-data
This format:
Breaks the request body into multiple parts
Each part can contain text fields or files
Cannot be parsed by default Express body parsers
So without middleware, Express simply cannot read file data.
What is Multer?
Multer is a middleware specifically designed to handle multipart/form-data.
It:
Parses incoming file data
Stores files (locally or memory)
Attaches file info to the request object
Think of Multer as a bridge between raw file data and usable JavaScript objects.
Understanding the Upload Lifecycle
Here’s what happens when a file is uploaded:
Client sends a form with
multipart/form-dataRequest reaches Express
Multer intercepts the request
File is processed and stored
File metadata is attached to:
req.file(single file)req.files(multiple files)
Your route handler uses this data
Installing Multer
npm install multer
Basic Setup
const express = require("express");
const multer = require("multer");
const app = express();
Storage Configuration (Basic)
By default, Multer stores files in memory. But usually, you want local storage.
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads/");
},
filename: function (req, file, cb) {
cb(null, Date.now() + "-" + file.originalname);
}
});
const upload = multer({ storage });
Key Concepts:
destination → where file is stored
filename → how file is named
Handling Single File Upload
app.post("/upload", upload.single("profile"), (req, res) => {
console.log(req.file);
res.send("File uploaded successfully");
});
Important:
"profile"must match the form input nameFile info is available in
req.file
Handling Multiple File Uploads
Option 1: Multiple files with same field
app.post("/upload-multiple", upload.array("photos", 5), (req, res) => {
console.log(req.files);
res.send("Multiple files uploaded");
});
"photos"→ field name5→ max number of files
Option 2: Different fields
app.post("/upload-fields", upload.fields([
{ name: "avatar", maxCount: 1 },
{ name: "documents", maxCount: 3 }
]), (req, res) => {
console.log(req.files);
res.send("Files uploaded");
});
Serving Uploaded Files
Once files are stored locally, you need to serve them.
app.use("/uploads", express.static("uploads"));
Now files are accessible via:
http://localhost:3000/uploads/filename.jpg
Example HTML Form
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="profile" />
<button type="submit">Upload</button>
</form>
Key Point:
enctype="multipart/form-data"is mandatory
Common Mistakes to Avoid
❌ Forgetting
enctype="multipart/form-data"❌ Mismatched field name between form and Multer
❌ Not creating the
uploads/directory❌ Trying to use
express.json()for file uploads
Minimal Mental Model
Express alone → handles JSON/text
Multer → handles files
multipart/form-data → required format
When to Use Multer
Use Multer when:
Uploading profile images
Uploading documents (PDF, resumes)
Handling media files
Avoid overcomplicating early:
Don’t jump to cloud storage yet (S3, Cloudinary)
First master local uploads + serving