Skip to main content

Command Palette

Search for a command to run...

Handling File Uploads in Express with Multer

Updated
4 min read
Handling File Uploads in Express with Multer
A
Graduated In Computer Application (BCA) | Love Building Systems | Currently learning Full Stack Development with ChaiCode Web-Dev 26 Cohort

Handling file upload in express is the fundamental task, but it requried a different apporaces then handiing standard json or url encoded data. Here is a guide to understand multer.

Why file uploads need middleware

When you send a standard form data or json object, express easily parse it by using its builtin parser like express.json(). However, files are binary data. To send them through the HTTP protocol brower use a special encoding type called multipart/form-data.

Standard body parsers are not equiped to handle this complex, multi-part stream wihtout a specialized middleares like multer, your req.body would be empty, and the file data would simply lost in the request stream. Middleware act as a bridge that:

  1. intercept the raw request stream.
  2. identified the different part like fields vs file.
  3. parse the files and populates rea.file or req.files

What Multer is

Multer is a node.js middleware for handling multipart form data, it is built on top of the busboy to be extremly efficient.

As of 2026, it is crucial to use multer version 2.1.0 or higher to ensure your app is protected against several high-severity denial-of-service (DOS) vulnerabilities (CVE-2026-3304) found in older versions.

  • Pirmary Role: it adds a body and file or files object to the request object.
  • Security Notes: never use a multer as a global middleware like app.use(upload.any()). Only apply it to the specific routes needs to handle uploads to prevent mulicious users from flooding your server with unwanted files.

Handling single file upload

For a single file like a profile picture, you use the .single() mehtod. This methods takes the name of the input fields from your HTML forms.

const express = require("express");
const multer = require("multer");
const upload = multer({ dest: "uploads/" }); // Basic setup

const app = express();

app.post("/upload-profile", upload.single("avatar"), (req, res) => {
  // req.file contains information about the file
  // req.body contains text fields (like username)
  console.log(req.file);
  res.send("File uploaded successfully!");
});

Handling multiple file uploads

If you need to upload multiple files under the same field name like gallery of images, use .array(). if they are in different fields, use .fields().

Using .array()

// Accepts up to 5 files with the field name 'photos'
app.post("/upload-gallery", upload.array("photos", 5), (req, res) => {
  // Access files via req.files (an array)
  console.log(req.files);
  res.send(`${req.files.length} files uploaded.`);
});

Using .fields()

const uploadMultiple = upload.fields([
  { name: "avatar", maxCount: 1 },
  { name: "gallery", maxCount: 8 },
]);

app.post("/register", uploadMultiple, (req, res) => {
  // req.files['avatar'][0] -> the profile image
  // req.files['gallery'] -> array of gallery images
});

Storage configuration basics

The default dest option is easy but limited, it renames files with hashes with extentios. To gain full controll, use diskstorage.

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "uploads/"); // Ensure this folder exists
  },
  filename: function (req, file, cb) {
    // Create a unique filename: timestamp + original name
    const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
    cb(
      null,
      file.fieldname +
        "-" +
        uniqueSuffix +
        "." +
        file.originalname.split(".").pop(),
    );
  },
});

const upload = multer({ storage: storage });
Options Best Use Cases
Disk Storage Large files or when you want a server holds fils long-terms
Memory Storage Small files or when you intended to immediatly upload them to storage services

Serving uploaded files

By default files in you project directory are not accessible to the public. To allow users to view its uploaded files, you must use the express.static() built-in middleware.

// This makes the 'uploads' folder publicly accessible
app.use("/uploads", express.static("uploads"));

Now, if a file is served as uploades/my-pic.jpg, it can be accessed via mysite.com/uploads/my-pic.jpg.

Summary

Standard parsers can't handle binary multipart/form-data, so Multer acts as the essential bridge. It intercepts the request stream, parsing files into req.file or req.files.

Use .single() for one file and .array() or .fields() for multiple. While basic setups are quick, diskStorage provides the control needed to customize filenames and directories. For security, apply it only to specific routes. Finally, expose your "uploads" folder using express.static to make files accessible via URL. It’s the standard way to turn raw binary uploads into manageable server assets.

Are you planning to store these files locally on your server, or are you looking to pipe them directly to a cloud provider like AWS S3?