Handling File Uploads in Express with Multer
File uploads are one of the most common backend features.
Examples:
profile pictures
resumes
PDFs
product images
videos
But uploading files in Express is different from handling normal JSON data.
Because files are not sent as regular text.
That’s why middleware like Multer exists.
Let’s understand how file uploads actually work in Express step-by-step.
Why File Uploads Need Middleware
Express can easily handle JSON requests using:
express.json()
because JSON is structured text data.
But file uploads work differently.
When a browser uploads files, it sends data using:
multipart/form-data
This format contains:
file binary data
text fields
metadata
Normal Express parsers cannot process this automatically.
That’s where Multer comes in.
What Is multipart/form-data?
When uploading files through forms, browsers package data differently.
Example form:
<form enctype="multipart/form-data">
The:
multipart/form-data
encoding allows sending:
files
images
text fields
inside the same request.
Without this format:
- files cannot be transferred properly
What Is Multer?
Multer is Express middleware for handling:
multipart/form-data
especially file uploads.
It helps:
parse uploaded files
store files
access file metadata
manage upload handling
Without Multer, handling raw file streams manually becomes complicated.
Installing Multer
Install using npm:
npm install multer
Basic Express Setup
Example:
const express = require("express");
const multer = require("multer");
const app = express();
Storage Configuration Basics
Multer needs to know:
- where files should be stored
Simple example:
const upload = multer({
dest: "uploads/"
});
This means:
“Store uploaded files inside the uploads folder.”
Folder Structure
Example:
project/
├── uploads/
├── server.js
Uploaded files will appear inside:
uploads/
Why Storage Configuration Exists
When users upload files:
- server must physically save them somewhere
Without storage configuration:
- uploaded files would disappear after request completion
Multer handles temporary parsing and file saving automatically.
Handling Single File Upload
Example route:
app.post("/upload", upload.single("image"), (req, res) => {
res.send("File Uploaded");
});
Understanding upload.single()
upload.single("image")
means:
expect one uploaded file
field name should be
"image"
Example frontend field:
<input type="file" name="image">
The field names must match.
What Happens Internally?
Flow:
Client uploads file
↓
Multer middleware intercepts request
↓
File parsed from multipart data
↓
File stored in uploads folder
↓
Request continues to route handler
↓
Response sent back
Accessing Uploaded File Information
Multer adds file data inside:
req.file
Example:
app.post("/upload", upload.single("image"), (req, res) => {
console.log(req.file);
res.send("Uploaded");
});
Example File Metadata
{
filename: "abc123",
originalname: "photo.png",
mimetype: "image/png",
size: 204800
}
This information helps:
store file paths
validate uploads
save references in database
Handling Multiple File Uploads
Sometimes users upload multiple files.
Example:
gallery images
multiple documents
Multer provides:
upload.array()
Example:
app.post("/photos", upload.array("images", 5), (req, res) => {
res.send("Multiple Files Uploaded");
});
Understanding upload.array()
upload.array("images", 5)
means:
accept files from
"images"fieldallow maximum 5 files
Uploaded files become available inside:
req.files
Serving Uploaded Files
Uploading files is only half the system.
Users also need access to uploaded content.
By default, uploaded folders are not publicly accessible.
Static File Serving
Express provides:
express.static()
Example:
app.use("/uploads", express.static("uploads"));
Now files inside:
uploads/
can be accessed through URLs like:
http://localhost:3000/uploads/file.jpg
Upload Lifecycle Overview
Client selects file
↓
Browser sends multipart/form-data request
↓
Multer middleware parses request
↓
File stored on server
↓
Route handler executes
↓
Response returned
↓
File accessible later via URL
Important Security Considerations
File uploads can be dangerous if handled carelessly.
Because users may upload:
malicious files
huge files
fake extensions
executable scripts
Safe handling is important.
1. Limit File Size
Example:
const upload = multer({
dest: "uploads/",
limits: {
fileSize: 5 * 1024 * 1024
}
});
This limits uploads to 5MB.
2. Validate File Types
Never trust file extensions alone.
Example dangerous file:
virus.exe renamed as image.png
Always validate MIME types.
3. Rename Files Safely
Many systems generate random filenames automatically.
This helps avoid:
collisions
overwriting
malicious filenames
4. Avoid Public Access to Sensitive Files
Not every uploaded file should be publicly accessible.
Examples:
invoices
private documents
internal reports
Some uploads should require authentication before access.
Simple Mental Model
Think of Multer like a delivery manager.
Browser
“Sends package.”
Multer
“Receives, parses, and stores package.”
Express Route
“Processes request after upload handling finishes.”
Handling file uploads in Express requires more than just accepting files.
A complete upload system involves:
multipart parsing
middleware handling
storage management
static serving
security validation
Multer simplifies this entire process by handling:
file parsing
storage
metadata extraction
Once you understand:
multipart/form-data
middleware flow
storage handling
static serving
building upload systems in Express becomes much easier.