Storing Uploaded Files and Serving Them in Express
When building real-world applications, handling file uploads (images, PDFs, videos, etc.) is a common requirement. But uploading is just one part β storing, serving, and securing those files is equally important.
In this guide, weβll break down how file storage works in Node.js with Express, along with best practices used in production systems.
π¦ Where Uploaded Files Are Stored
When a user uploads a file, the backend must decide where to store it. Broadly, there are two approaches:
1. Local File System (Server Storage)
Files are stored directly on the server's disk.
Example structure:
project-root/
β
βββ uploads/
β βββ images/
β β βββ img1.jpg
β β βββ img2.png
β β
β βββ documents/
β βββ file1.pdf
β
βββ server.js
How it works:
A middleware like
multersaves files into a folder (uploads/)File path is stored in your database
Later, files are served via Express
2. External Storage (Cloud / Object Storage)
Instead of storing files locally, you use services like:
AWS S3
Cloudinary
Firebase Storage
How it works:
File is uploaded directly (or via backend) to cloud storage
You store the file URL in your database
Files are served directly from CDN
βοΈ Local Storage vs External Storage
| Feature | Local Storage | External Storage |
|---|---|---|
| Setup | Simple | Requires configuration |
| Scalability | Poor | Highly scalable |
| Performance | Limited | CDN optimized |
| Cost | Free (initially) | Pay-as-you-scale |
| Reliability | Risky (server crash = data loss) | Highly reliable |
π Rule of thumb:
Use local storage for small projects / learning
Use external storage for production apps
π Serving Static Files in Express
Express provides a built-in middleware to serve static files:
const express = require("express");
const path = require("path");
const app = express();
// Serve files from "uploads" folder
app.use("/uploads", express.static(path.join(__dirname, "uploads")));
What this does:
Maps
/uploadsURL path to the actualuploads/folderMakes files publicly accessible
π Accessing Uploaded Files via URL
If you have a file stored like:
uploads/images/profile.jpg
You can access it via:
http://localhost:3000/uploads/images/profile.jpg
π This works because of:
app.use("/uploads", express.static("uploads"));
π οΈ Upload Example Using Multer
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads/images");
},
filename: function (req, file, cb) {
cb(null, Date.now() + "-" + file.originalname);
}
});
const upload = multer({ storage: storage });
app.post("/upload", upload.single("file"), (req, res) => {
res.send({
message: "File uploaded successfully",
filePath: req.file.path
});
});
π Security Considerations for File Uploads
This is where most beginners make mistakes. File uploads are a major attack surface.
1. Validate File Type
Never trust client input.
fileFilter: (req, file, cb) => {
if (file.mimetype.startsWith("image/")) {
cb(null, true);
} else {
cb(new Error("Only images allowed"), false);
}
}
2. Limit File Size
limits: { fileSize: 5 * 1024 * 1024 } // 5MB
3. Avoid Executable Files
Block .js, .exe, .sh, etc.
4. Use Unique File Names
Prevent overwriting:
Date.now() + "-" + file.originalname
5. Store Outside Public Root (Advanced)
Instead of directly exposing /uploads, use a controller:
app.get("/file/:name", (req, res) => {
res.sendFile(path.join(__dirname, "uploads", req.params.name));
});
6. Scan Files (Production)
Use antivirus or scanning tools for:
PDFs
Documents
User uploads
Here's a prod grade structure ( it has sharding, careful if following this )
π Static File Serving Concept (Important)
Static files are files that:
Donβt change dynamically
Are served directly to the client
Examples:
Images
CSS files
PDFs
Express acts like a file server when using:
express.static()
π Instead of writing routes manually, Express:
Locates the file
Streams it to the client
Sets correct headers
Here's a prod grade example -
π§ Best Practices Summary
Use
multerfor handling uploadsSeparate folders by file type (images, docs, etc.)
Never trust user-uploaded files
Prefer cloud storage in production
Use CDN for faster delivery
Store only file paths/URLs in DB (not actual files)
π Final Thought
File handling may look simple, but at scale, it becomes a system design problem involving:
Storage architecture
Security layers
CDN optimization
Cost management