Skip to main content

Command Palette

Search for a command to run...

Storing Uploaded Files and Serving Them in Express

Updated
4 min read
Storing Uploaded Files and Serving Them in Express

File uploads are a core feature in modern web applications.

Whether users are uploading profile pictures, documents, resumes, or media files — your backend needs a reliable way to store, manage, and serve those files back when needed.

If you're working with Node.js and Express, understanding how file storage works is essential for building real-world applications.

In this article, we’ll explore where uploaded files are stored, how Express serves them, how users access them via URLs, and what security practices you should follow.

Why File Handling Matters

When a user uploads a file, your backend must answer a few critical questions:

  • Where should this file be stored?

  • How will we access it later?

  • How do we serve it efficiently?

  • How do we prevent unsafe uploads?

Poor handling can lead to:

  • Broken file links

  • Server crashes

  • Security vulnerabilities

  • Data loss

So let’s break it down step by step.

Where Uploaded Files Are Stored

When using Express, uploaded files are typically stored in one of the following:

  • Local server storage (file system)

  • External storage services (cloud-based)

The simplest approach is local storage, especially for learning and small projects.

Example Folder Structure

Here:

  • uploads/ is where user files are stored

  • Files are organized into categories (images, documents)

Upload Storage Folder Structure (Diagram)

This keeps your storage organized and scalable.

Local Storage vs External Storage

Choosing where to store files depends on your application scale.

Local Storage

Files are stored directly on your server.

Example path:

/uploads/images/profile.png

Advantages:

  • Simple to implement

  • No external dependencies

  • Fast for small apps

Limitations:

  • Not scalable

  • Risk of data loss if server crashes

  • Difficult to handle multiple servers

External Storage (Cloud)

Examples:

  • AWS S3

  • Cloudinary

  • Firebase Storage

Advantages:

  • Highly scalable

  • Reliable and redundant

  • CDN support for fast delivery

Limitations:

  • Requires setup

  • Costs involved

  • Slight complexity increase

When to Use What

  • Use local storage for learning and small apps

  • Use cloud storage for production-level applications

Handling File Uploads in Express

To upload files in Express, we commonly use middleware like:

npm install multer

Basic Setup

const express = require("express");
const multer = require("multer");
const path = require("path");

const app = express();

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "uploads/images");
  },
  filename: function (req, file, cb) {
    const uniqueName = Date.now() + path.extname(file.originalname);
    cb(null, uniqueName);
  }
});

const upload = multer({ storage: storage });

app.post("/upload", upload.single("image"), (req, res) => {
  res.send("File uploaded successfully");
});

app.listen(3000);

This stores uploaded files inside uploads/images.

Serving Static Files in Express

Uploading files is only half the job.

You also need to serve them so users can access them via URL.

Express provides a built-in way to serve static files.

Static Middleware

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

This means:

Any file inside uploads/ can be accessed via:

http://localhost:3000/uploads/<filename>

Example:

http://localhost:3000/uploads/images/profile.png

Now your uploaded files are publicly accessible.

Static File Serving Flow

This is exactly how images, PDFs, and files are served.

Accessing Uploaded Files via URL

Once static serving is enabled:

If file is stored as:

uploads/images/17123456789.png

You can access it via:

http://localhost:3000/uploads/images/17123456789.png

This URL can be:

  • Stored in database

  • Sent to frontend

  • Used in <img> tags

Example:

<img src="http://localhost:3000/uploads/images/17123456789.png" />

Important Concept: Public vs Private Files

By default, static serving makes files publicly accessible.

But not all files should be public.

Examples of sensitive files:

  • User documents

  • Private PDFs

  • Personal data

For such cases:

  • Do NOT expose via static middleware

  • Serve files through protected routes

  • Add authentication checks

Security Considerations for File Uploads

File uploads can be risky if not handled carefully.

Here are essential practices.

Validate File Type

Only allow specific file types.

fileFilter: function (req, file, cb) {
  if (file.mimetype.startsWith("image/")) {
    cb(null, true);
  } else {
    cb(new Error("Only images allowed"), false);
  }
}

Limit File Size

Prevent large uploads.

limits: { fileSize: 2 * 1024 * 1024 } // 2MB 

Use Unique File Names

Avoid overwriting files.

Already handled with:

Date.now()

Avoid Executable Files

Never allow:

  • .exe

  • .js

  • .sh

These can be dangerous.

Store Outside Public Folder (if needed)

Sensitive files should not be directly accessible.

Sanitize File Names

Prevent path traversal attacks.

Use HTTPS in Production

Protect file transfer.