Node.js File Uploads

File uploads let visitors send photos, documents, and other files to your server. Profile pictures and resume forms use this feature. Express handles uploads with a popular library called Multer.

How an Upload Works

A normal form sends short text. A file is large and binary, so the browser packs it in a special format called multipart form data. Multer unpacks that format and saves the file.

 +---------+  multipart data  +--------+  saves   +-----------+
 | Browser | ---------------> | Multer | -------> | uploads/  |
 +---------+                  +--------+          +-----------+
                                  |
                                  v
                       req.file (file details)
                       req.body (text fields)

Install Multer

npm install express multer

Build the Upload Form

The form needs the enctype attribute. Without it, the file never leaves the browser.

<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="text" name="title">
  <input type="file" name="photo">
  <button type="submit">Upload</button>
</form>

Save One File

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

const app = express();
const upload = multer({ dest: "uploads/" });

app.post("/upload", upload.single("photo"), (req, res) => {
  console.log(req.file);
  console.log(req.body.title);
  res.send("File saved.");
});

app.listen(3000);

The text photo inside upload.single matches the input name in the form.

What req.file Contains

  • originalname holds the name on the visitor's computer.
  • filename holds the saved name.
  • mimetype holds the file type, such as image/png.
  • size holds the file size in bytes.
  • path holds the saved location.

Control File Names and Folders

The simple option saves files with random names and no extension. Use diskStorage for full control.

const path = require("path");

const storage = multer.diskStorage({
  destination: (req, file, cb) => cb(null, "uploads/"),
  filename: (req, file, cb) => {
    const unique = Date.now() + "-" + Math.round(Math.random() * 1e9);
    cb(null, unique + path.extname(file.originalname));
  }
});

const upload = multer({ storage });

A unique name stops one visitor from overwriting another visitor's file.

Upload Many Files

// Many files from one input
app.post("/gallery", upload.array("photos", 5), (req, res) => {
  res.send(req.files.length + " files saved.");
});

// Files from different inputs
const fields = upload.fields([
  { name: "avatar", maxCount: 1 },
  { name: "documents", maxCount: 3 }
]);
upload.single("photo")      --> req.file   (one file)
upload.array("photos", 5)   --> req.files  (list of files)
upload.fields([...])        --> req.files  (grouped by input name)

Set Limits

Limits protect your server from huge files.

const upload = multer({
  storage,
  limits: { fileSize: 2 * 1024 * 1024 }  // 2 MB
});

Filter File Types

A filter accepts or rejects each file before saving.

const allowed = ["image/jpeg", "image/png", "image/webp"];

const upload = multer({
  storage,
  limits: { fileSize: 2 * 1024 * 1024 },
  fileFilter: (req, file, cb) => {
    if (allowed.includes(file.mimetype)) {
      cb(null, true);
    } else {
      cb(new Error("Only JPG, PNG, or WEBP images are allowed."));
    }
  }
});

Handle Upload Errors

app.use((err, req, res, next) => {
  if (err instanceof multer.MulterError) {
    return res.status(400).send("Upload problem: " + err.message);
  }
  if (err) {
    return res.status(400).send(err.message);
  }
  next();
});

Place this handler below all routes.

Show Uploaded Files

Serve the upload folder as static files to display images.

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

A saved file named 171-photo.png opens at /files/171-photo.png.

Safety Rules

  • Limit file size and file type every time.
  • Rename files and ignore the visitor's file name.
  • Store uploads outside the code folder.
  • Never run uploaded files as programs.
  • Scan documents for harmful content when your app allows public uploads.
  • Consider cloud storage for large projects.

Practice Tasks

  • Build a profile picture form that accepts one image up to 1 MB.
  • Rename each saved file with a timestamp.
  • Reject a PDF file and show a friendly message.