Skip to content

Guide · Open source

How to use multer: file uploads in Node.js and Express

Updated · written with AI from the project's own documentation and checked against our catalogue data

Multer is a Node.js middleware that receives files and text fields sent from HTML forms using the multipart/form-data format. It is built on busboy and is commonly used with Express. This guide shows you how to install it, wire it into a route, choose where files are stored and handle the limits and naming rules that matter for safe uploads.

Multerexpressjs/multer · ★ 12.1k · MIT

Quick start

  1. 1Install Multer. Run npm install multer in your Node.js project.
  2. 2Set the form encoding. Add enctype="multipart/form-data" to the HTML form and give the file input a name.
  3. 3Create the upload middleware. Call multer with an options object such as dest, or with a storage engine.
  4. 4Attach it to a route. Pass upload.single, upload.array, upload.fields or upload.none to the route that receives the form.
  5. 5Read the results. Use req.file for single uploads, req.files for array and fields uploads, and req.body for text fields.
  6. 6Validate and rename. Use fileFilter, limits and a custom filename function to control what is accepted and how files are named.

Install Multer with npm

Multer is installed from npm. You need Node.js and npm available on your machine.

$ npm install multer

Create an upload form that Multer can read

The HTML form must include enctype="multipart/form-data", otherwise Multer will not process it. The name of the file input must match the field name you pass to Multer on the server. If the two differ, the upload fails.

  • Set method="post" and enctype="multipart/form-data" on the form.
  • Give the file input a name, such as avatar, and use the same name in your server code.
<form action="/profile" method="post" enctype="multipart/form-data"> <input type="file" name="avatar" /> </form>

Accept a single file, several files or mixed fields

Multer provides route helpers for each case. Use .single() for one file, which is stored in req.file. Use .array() for several files under one field name, which are stored in req.files. Use .fields() when a form has more than one file field, which stores an object keyed by field name in req.files. Text fields always appear in req.body.

  • .single(fieldname) stores the file in req.file.
  • .array(fieldname[, maxCount]) stores files in req.files and can error if more than maxCount arrive.
  • .fields(fields) takes an array of objects with name and optionally maxCount.
  • .none() accepts text fields only and errors with LIMIT_UNEXPECTED_FILE if a file is sent.
  • .any() accepts all files, but see the warning in the safety section.
const express = require('express') const multer = require('multer') const upload = multer({ dest: 'uploads/' }) const app = express() app.post('/profile', upload.single('avatar'), function (req, res, next) { // req.file is the `avatar` file // req.body will hold the text fields, if there were any }) app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) { // req.files is array of `photos` files // req.body will contain the text fields, if there were any }) const uploadMiddleware = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }]) app.post('/cool-profile', uploadMiddleware, function (req, res, next) { // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files // req.body will contain the text fields, if there were any })

Handle text-only multipart forms

If a form contains text fields and no files, use upload.none(). Text values are then available in req.body.

const express = require('express') const app = express() const multer = require('multer') const upload = multer() app.post('/profile', upload.none(), function (req, res, next) { // req.body contains the text fields })

Choose where uploaded files are stored

The simplest option is dest, which tells Multer which folder to save files to. If you omit the options object, files are kept in memory and never written to disk. For more control, use the storage option with DiskStorage or MemoryStorage. With DiskStorage you can set destination and filename functions. If you pass destination as a function, you are responsible for creating that directory. When you pass a string, Multer creates the directory for you.

Multer renames files by default to avoid naming conflicts. You can replace that behaviour with your own filename function, for example one that uses random bytes.

  • dest: a simple folder path for most apps.
  • Memory storage: files are available as a Buffer on file.buffer.
  • Disk storage: files expose destination, filename and path.
const crypto = require('crypto') const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, '/tmp/my-uploads') }, filename: function (req, file, cb) { crypto.randomBytes(16, function (err, raw) { if (err) return cb(err) cb(null, file.fieldname + '-' + raw.toString('hex')) }) } }) const upload = multer({ storage: storage })

Use limits and filters to control what is accepted

The options object accepts fileFilter, which controls which files are accepted, and limits, which bounds the uploaded data. Files skipped by fileFilter do not count towards maxCount. Use limits.files to bound how many files are read from a request.

The README also notes that preservePath keeps the full client-supplied path in file.originalname. Multer does not sanitise that value, so treat it as untrusted and validate it before using it in a filename.

  • fileFilter: decide per file whether to accept it.
  • limits: cap uploaded data, including limits.files.
  • preservePath: off by default; if enabled, file.originalname can include client-supplied path segments.

Keep uploads off global middleware

The README warns that you should never add Multer as global middleware, because a malicious user could upload files to a route you did not anticipate. Attach upload handlers only to routes that are designed to receive files.

  • Apply upload.single, upload.array, upload.fields or upload.none to specific routes.
  • Do not call app.use(upload...) for the whole app.

What people use it for

  • Letting users upload a profile avatar in an Express app with upload.single.
  • Accepting a gallery of up to a set number of photos with upload.array and maxCount.
  • Receiving a form that has separate avatar and gallery fields using upload.fields.
  • Keeping small uploads in memory with the default setup, then processing the buffer in code.
  • Saving uploads to a chosen folder with a custom filename function.

Frequently asked questions

How do I install multer?

Run npm install multer in your Node.js project. The README lists Node.js and npm as the prerequisites.

Is multer free to use?

Multer is open source under the MIT licence, as stated in the project's listing. Check the licence file in the repository for the full terms.

Why is req.file undefined when I upload a file?

Multer only processes multipart/form-data requests, so confirm the form has enctype="multipart/form-data". Also make sure the field name in the HTML matches the name passed to upload.single or upload.array, because mismatched names cause the upload to fail.

Where does multer store uploaded files?

If you set dest, files go to that folder. If you omit the options object, files are kept in memory and never written to disk. You can also use DiskStorage or MemoryStorage through the storage option.

Can multer accept multiple files?

Yes. Use upload.array(fieldname, maxCount) for several files under one field, or upload.fields for several named file fields. Files are placed in req.files.

What are the alternatives to multer?

The project lists busboy, formidable and multiparty as comparable projects. Multer itself is built on top of busboy.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

Multer is a good fit for Node.js developers adding file upload to an Express app, especially if they want control over storage and file naming. It is not suitable for non-Node.js projects or for apps that only accept non-multipart requests. If you need a lower-level parser, consider busboy directly, or compare formidable and multiparty.

Install options & downloads