npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xof/multer

v1.0.0

Published

Fast, streaming-first multipart/form-data middleware for Node.js.

Readme

@xof/multer

Fast, streaming-first multipart/form-data middleware for Node.js.

npm Node.js License

@xof/multer is a lightweight and efficient multipart/form-data middleware for handling file uploads and form fields in Node.js applications.

It provides streaming request processing, configurable storage engines, upload limits, multiple-file handling, and structured errors.


Features

  • 🚀 Streaming multipart parser
  • 📦 Memory storage
  • 💾 Disk storage
  • 📁 Single file uploads
  • 📚 Multiple file uploads
  • 🗂️ Multiple field uploads
  • 📝 Multipart form fields
  • 🛡️ Configurable upload limits
  • ⚡ Low memory overhead
  • 🧹 Automatic cleanup on failed uploads
  • ❌ Structured errors
  • 🔌 Storage engine architecture
  • 🟢 Native Node.js HTTP stream support

Requirements

  • Node.js >= 18

Installation

npm install @xof/multer

Basic Usage

const multer = require('@xof/multer');

const upload = multer();

server.post('/upload', upload.single('file'), (req, res) => {
 res.json({
  status: true,
	data: {
	  body: req.body,
		file: req.file
       }
	});
  }
);

Storage

Memory Storage

Stores the uploaded file in memory.

const multer = require('@xof/multer');

const upload = multer({
	storage: multer.memoryStorage()
});

The resulting file contains a buffer property:

console.log(req.file.buffer);

Memory storage is useful when the application needs to process the file directly without creating a permanent file on disk.


Disk Storage

Stores uploaded files on the filesystem.

const upload = multer({
	storage: multer.diskStorage({
		destination: './uploads'
	})
});

A disk-stored file can expose properties such as:

{
	fieldname,
	originalname,
	filename,
	destination,
	path,
	mimetype,
	size
}

The destination directory is created when required by the storage engine.


Upload Modes

Single File

Accept one file from a specific field.

upload.single('avatar')

Example:

server.post(
	'/avatar',
	upload.single('avatar'),
	(req, res) => {
		res.json({
			status: true,
			data: req.file
		});
	}
);

Multiple Files

Accept multiple files from the same field.

upload.array('photos', 10)

Example:

server.post(
	'/photos',
	upload.array('photos', 10),
	(req, res) => {
		res.json({
			status: true,
			data: req.files
		});
	}
);

Multiple Fields

Accept multiple configured file fields.

upload.fields([
	{
		name: 'avatar',
		maxCount: 1
	},
	{
		name: 'documents',
		maxCount: 5
	}
])

Example:

server.post(
	'/profile',
	upload.fields([
		{
			name: 'avatar',
			maxCount: 1
		},
		{
			name: 'documents',
			maxCount: 5
		}
	]),
	(req, res) => {
		res.json({
			status: true,
			data: req.files
		});
	}
);

Any Files

Accept files from any multipart field.

upload.any()

Example:

server.post(
	'/files',
	upload.any(),
	(req, res) => {
		res.json({
			status: true,
			data: req.files
		});
	}
);

Only use this mode when arbitrary file fields are intentionally allowed.


No Files

Accept multipart form fields while rejecting file uploads.

upload.none()

Example:

server.post(
	'/form',
	upload.none(),
	(req, res) => {
		res.json({
			status: true,
			data: req.body
		});
	}
);

Form Fields

Text fields are available through req.body.

server.post(
	'/register',
	upload.single('avatar'),
	(req, res) => {
		res.json({
			status: true,
			data: {
				username: req.body.username,
				email: req.body.email
			}
		});
	}
);

Multiple values for the same field can be represented as arrays.


Upload Limits

Limits can be configured through the limits option.

const upload = multer({
	limits: {
		fileSize: 100 * 1024 * 1024,
		files: 10,
		fields: 50,
		fieldSize: 1024 * 1024,
		parts: 100
	}
});

Available options:

| Option | Description | |---|---| | fileSize | Maximum size of a single file | | files | Maximum number of files | | fields | Maximum number of form fields | | fieldSize | Maximum size of a field | | parts | Maximum number of multipart parts | | fieldNameSize | Maximum field-name size | | headerSize | Maximum multipart header size |


File Object

A processed file contains information about the uploaded file.

{
	fieldname,
	originalname,
	encoding,
	mimetype,
	size
}

Storage engines may add additional properties.

For example, memory storage can provide:

req.file.buffer

Disk storage can provide:

req.file.filename
req.file.destination
req.file.path

Error Handling

Upload errors contain a machine-readable code.

try {
	// upload processing
} catch (error) {
	console.log(error.code);
}

Common error codes:

| Code | Description | |---|---| | LIMIT_FILE_SIZE | File exceeds the configured size | | LIMIT_FILE_COUNT | File count limit exceeded | | LIMIT_FIELD_COUNT | Field count limit exceeded | | LIMIT_FIELD_VALUE | Field value exceeds the configured size | | LIMIT_FIELD_KEY | Field name is too long | | LIMIT_UNEXPECTED_FILE | Unexpected file field | | INVALID_MULTIPART | Invalid multipart request | | INVALID_BOUNDARY | Invalid multipart boundary | | REQUEST_ABORTED | Upload was aborted |


API

multer(options)

Creates an upload middleware.

const upload = multer({
	storage,
	limits
});

Options

| Option | Type | Description | |---|---|---| | storage | Storage | Storage engine | | limits | Object | Multipart limits | | fileFilter | Function | File validation |


multer.memoryStorage()

Creates a memory-based storage engine.

const storage = multer.memoryStorage();

multer.diskStorage(options)

Creates a filesystem storage engine.

const storage = multer.diskStorage({
	destination: './uploads'
});

upload.single(field)

Accepts a single file.

upload.single('file')

upload.array(field, maxCount)

Accepts multiple files from one field.

upload.array('files', 10)

upload.fields(fields)

Accepts multiple configured fields.

upload.fields([
	{
		name: 'avatar',
		maxCount: 1
	},
	{
		name: 'files',
		maxCount: 5
	}
])

upload.any()

Accepts files from any field.

upload.any()

upload.none()

Accepts multipart fields without files.

upload.none()

Example

const multer = require('@xof/multer');

const upload = multer({
	storage: multer.diskStorage({
		destination: './uploads'
	}),
	limits: {
		fileSize: 100 * 1024 * 1024
	}
});

server.post('/upload',
 upload.single('file'), (req, res) => {
   res.status(201).json({
	 status: true,
	  data: {
		filename: req.file.filename,
		 originalname: req.file.originalname,
		 mimetype: req.file.mimetype,
		 size: req.file.size,
		path: req.file.path
	}
   });
  }
);

Test with cURL:

curl -i \
	-F "file=@./test.png" \
	http://127.0.0.1:8080/upload

Performance

@xof/multer processes multipart data as a stream instead of requiring the entire request to be loaded before parsing.

This makes it suitable for:

  • Large file uploads
  • Multiple-file uploads
  • VPS applications
  • Long-running Node.js services
  • Memory-sensitive applications

For large uploads, disk storage is generally preferable to memory storage.


Changelog


License

Released under the MIT License.