Skip to content

File Uploads

intermediate2 min read
  • Express
  • Node.js

Accepting binary files over HTTP with multipart form data, then validating type and size and storing the file safely outside the database.

Prerequisites

  • HTTP requests and request validation (see Related Topics)

What you'll understand

  • How files are sent over HTTP differently from JSON
  • Why uploads must be validated for type and size
  • Where uploaded files should actually be stored

Explanation

A file upload sends binary data, an image, a PDF, a spreadsheet, from a client to your server. Files are not sent as JSON; they travel as multipart form data, a request format designed to carry one or more binary parts alongside ordinary fields. On the server, middleware parses that multipart body and hands your handler the file and its metadata.

Uploads are a significant security and reliability surface, so validation is not optional. Check the file size against a limit before accepting it, or a large upload can exhaust memory and disk. Check the type, and do not trust the filename or the client-supplied content type alone, because both can be faked. Reject anything that does not match what the endpoint is meant to accept (see Related Topics).

Finally, decide where the file goes. Storing large binaries directly in your relational database is usually a poor fit; the common pattern is to store the file in a filesystem or an object store (such as cloud storage) and keep only a reference, the path or URL plus metadata, in the database. That keeps the database lean and serving efficient.

Examples

This TypeScript example uses multer middleware to accept a single file with a size limit, then reads its metadata:

import multer from 'multer';

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

app.post('/avatar', upload.single('file'), (req, res) => {
  if (!req.file) return res.status(400).json({ message: 'File required' });
  // req.file.mimetype, req.file.size, req.file.buffer are available here
  res.status(201).json({ size: req.file.size });
});

Common mistakes

  • Accepting uploads with no size limit, risking memory and disk exhaustion.
  • Trusting the client-supplied filename or content type to decide the file kind.
  • Storing large binary files directly in the relational database.
  • Saving files under the original filename, allowing overwrites or path tricks.

Best practices

  • Enforce a maximum file size and reject anything larger.
  • Validate the actual file type, not just the declared one (see Related Topics).
  • Store files in a filesystem or object store and keep a reference in the database.
  • Generate a safe, unique name for each stored file.

Further reading

Related topics