The Codex / Technologies / Express.js / File Uploads

File Uploads

Accepting files from clients - multer middleware, handling multipart form data, file validation, and storing uploads locally or in cloud storage.

What it is, in plain English: File uploads use a special request encoding called multipart/form-data, which express.json() cannot parse -- it's designed for binary file content, not JSON. Multer is the standard Express middleware for handling multipart uploads: it parses the incoming file data, makes it available on req.file (single) or req.files (multiple), and can validate file type/size before your route handler ever runs.

Why express.json() can't handle file uploads

File uploads use a different request format called multipart/form-data -- it can mix text fields and binary file content in one request. express.json() only understands JSON text, so a separate middleware is needed: multer.

Basic setup -- a single file upload

# npm install multer
import multer from "multer";

const upload = multer({ dest: "uploads/" });   // saves files to an "uploads" folder

app.post("/upload", upload.single("avatar"), (req, res) => {
  // "avatar" must match the form field name the client used
  console.log(req.file);
  // { fieldname: "avatar", originalname: "photo.jpg", mimetype: "image/jpeg",
  //   path: "uploads/a1b2c3...", size: 204800 }

  res.json({
    filename: req.file.filename,
    size:     req.file.size,
  });
});
<!-- The HTML form a client would submit from: -->
<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="avatar" />
  <button type="submit">Upload</button>
</form>
<!-- enctype="multipart/form-data" is REQUIRED for file uploads -->

Multiple files

// Multiple files under the SAME field name:
app.post("/gallery", upload.array("photos", 10), (req, res) => {
  // req.files is an ARRAY (not req.file) when using .array()
  res.json({ uploaded: req.files.length });
});

// Multiple DIFFERENT field names:
app.post("/profile", upload.fields([
  { name: "avatar", maxCount: 1 },
  { name: "coverPhoto", maxCount: 1 },
]), (req, res) => {
  // req.files.avatar[0], req.files.coverPhoto[0]
  res.json({ avatar: req.files.avatar[0].filename });
});

Restricting file types and size

const upload = multer({
  dest: "uploads/",
  limits: { fileSize: 5 * 1024 * 1024 },   // 5MB max
  fileFilter: (req, file, cb) => {
    const allowed = ["image/jpeg", "image/png", "image/webp"];
    if (!allowed.includes(file.mimetype)) {
      return cb(new Error("Only JPEG, PNG, and WebP images allowed"));
    }
    cb(null, true);   // accept the file
  },
});
Try It Yourself (Node.js logic)

Official Sources

The Codex links only to official documentation. No third-party tutorials.