Skip to main content

Command Palette

Search for a command to run...

Storing Uploaded Files and Serving Them in Express.js

Updated
β€’4 min read
Storing Uploaded Files and Serving Them in Express.js

When building modern web applications, handling file uploads (images, PDFs, videos, etc.) is a common requirement.

But uploading is just one part β€” we also need to store files properly, serve them efficiently, and secure them.

In this blog, we’ll learn everything end-to-end β€” from storage strategies to serving files via URLs in Express.js.

πŸš€ How File Upload Works?

Before diving deep, let’s understand the flow:

Client (Browser)
      ↓
Upload Request (multipart/form-data)
      ↓
Express Server (Multer or similar middleware)
      ↓
File Stored (Local / Cloud)
      ↓
File Served via URL

Where Uploaded Files Are Stored

There are two main storage approaches:

βœ… Option 1:

Local Storage (Server File System)

Files are stored inside your project folder.

Example structure:

project/
β”‚
β”œβ”€β”€ uploads/
β”‚   β”œβ”€β”€ images/
β”‚   β”œβ”€β”€ documents/
β”‚
β”œβ”€β”€ server.js

Example using Multer:

const multer = require('multer');

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: storage });

πŸ‘‰ Files will be stored inside /uploads.

☁️ Option 2:

External Storage (Cloud)

Instead of storing files on your server, you use services like:

  • AWS S3

  • Cloudinary

  • Firebase Storage

πŸ‘‰ Best for:

  • Scalability

  • Production apps

  • Handling large files


Local Storage vs External Storage

Feature Local Storage External Storage
Setup Easy Moderate
Cost Free Paid
Scalability Limited High
Performance Depends on server Optimized CDN
Best For Small apps / learning Production apps

πŸ‘‰ Conclusion:

  • Use local storage for development

  • Use cloud storage for production


πŸ“‚ Folder-Based Storage Structure

Organizing files properly is very important.

πŸ“Œ Good Practice Structure:

uploads/
β”‚
β”œβ”€β”€ images/
β”‚   β”œβ”€β”€ profile/
β”‚   β”œβ”€β”€ posts/
β”‚
β”œβ”€β”€ documents/
β”‚   β”œβ”€β”€ pdfs/
β”‚   β”œβ”€β”€ resumes/

πŸ‘‰ Benefits:

  • Easy to manage

  • Cleaner structure

  • Faster debugging


🌐 Serving Static Files in Express

Now comes the important part β€” how users access uploaded files.

Express Static Middleware:

const express = require('express');
const app = express();

app.use('/uploads', express.static('uploads'));

This means:

File stored at: uploads/image.png

Accessible via URL: http://localhost:3000/uploads/image.png


πŸ”—Accessing Uploaded Files via URL

Once files are stored and static middleware is set:

Example:

app.post('/upload', upload.single('file'), (req, res) => {
  res.json({
    fileUrl: `http://localhost:3000/uploads/${req.file.filename}`
  });
});

πŸ‘‰ Now frontend can directly use:

<img src="http://localhost:3000/uploads/12345-image.png" />

πŸ”„ Static File Serving Flow

Browser Request
     ↓
GET /uploads/image.png
     ↓
Express Static Middleware
     ↓
Search in "uploads/" folder
     ↓
File Found β†’ Sent to Browser
     ↓
File Displayed

πŸ” Security Considerations for File Uploads

This is VERY IMPORTANT (often ignored by beginners).

❌ Risks:

  • Malicious files (e.g., .exe, scripts)

  • Large file attacks (DoS)

  • Path traversal attacks


βœ… Best Practices:

  1. Validate File Type
fileFilter: (req, file, cb) => {
  if (file.mimetype.startsWith('image/')) {
    cb(null, true);
  } else {
    cb(new Error('Only images allowed'), false);
  }
}
  1. Limit File Size
limits: { fileSize: 2 * 1024 * 1024 } // 2MB
  1. Rename Files Safely πŸ‘‰ Avoid original names (can be risky)

πŸ‘‰ Avoid original names (can be risky)

Date.now() + '-' + file.originalname
  1. Store Outside Public Root (Advanced)

πŸ‘‰ Serve via controlled routes instead of direct access

5. Use Authentication

πŸ‘‰ Only logged-in users should upload/download files


Now Putting It All Together (Complete Example) JavaScript

const express = require('express');
const multer = require('multer');

const app = express();

const storage = multer.diskStorage({
  destination: (req, file, cb) => cb(null, 'uploads/'),
  filename: (req, file, cb) =>
    cb(null, Date.now() + '-' + file.originalname)
});

const upload = multer({ storage });

app.use('/uploads', express.static('uploads'));

app.post('/upload', upload.single('file'), (req, res) => {
  res.json({
    message: 'File uploaded successfully',
    url: `http://localhost:3000/uploads/${req.file.filename}`
  });
});

app.listen(3000, () => console.log('Server running on port 3000'));

Conclusion

Uploading and serving files in Express.js is a simple but important backend skill. By storing files properly, serving them with URLs, and following basic security practices, you can build reliable features like image or document uploads. Understanding this flow helps you create real-world, production-ready applications.

More from this blog

JavaScript

26 posts