@fastify/multipart, busboy, formidable, and multer are Node.js libraries designed to parse multipart/form-data requests, which are standard for handling file uploads and complex form submissions. multer is the de facto standard middleware for Express applications, offering a simple API for saving files to disk or memory. busboy is a high-performance streaming parser that serves as the engine for many other libraries, providing low-level control without built-in file storage. formidable is a robust, battle-tested library often used in standalone HTTP servers or frameworks like Koa, known for its ease of use and automatic file handling. @fastify/multipart is the official plugin for the Fastify framework, optimized for high throughput and async/await patterns, leveraging busboy under the hood.
Handling file uploads and multipart forms is a common requirement in backend development, but it is also one of the most error-prone areas if not managed correctly. The four main tools in the Node.js ecosystem—busboy, multer, formidable, and @fastify/multipart—approach this problem from different angles. Some prioritize raw speed and streaming control, while others focus on developer convenience and framework integration. Let's break down how they work, where they shine, and how to implement them in real-world scenarios.
The fundamental difference between these libraries lies in how they handle incoming data. busboy is a pure streaming parser. It processes data chunk by chunk as it arrives, never loading the entire file into memory unless you explicitly tell it to. This makes it incredibly efficient for large files.
multer and formidable are higher-level wrappers. They often buffer data to disk or memory to simplify the API. multer is specifically designed to act as Express middleware, intercepting requests before they reach your route handlers. @fastify/multipart bridges the gap, using busboy internally but exposing a modern async/await API that fits the Fastify ecosystem.
busboy: The Low-Level Enginebusboy gives you direct access to the stream. You must manually handle file events and decide where to pipe the data. It does not save files to disk automatically. This is perfect if you want to upload directly to Amazon S3 or another cloud service without touching your server's disk.
import Busboy from 'busboy';
import { pipeline } from 'node:stream/promises';
import { createWriteStream } from 'node:fs';
export async function handleUpload(req, res) {
const busboy = new Busboy({ headers: req.headers });
busboy.on('file', (name, file, info) => {
const { filename, mimeType } = info;
// Pipe directly to a file or cloud storage stream
const writeStream = createWriteStream(`./uploads/${filename}`);
file.pipe(writeStream);
});
busboy.on('finish', () => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'upload complete' }));
});
req.pipe(busboy);
}
multer: The Express Standardmulter simplifies the process for Express apps. You configure a storage engine (disk or memory) and attach the middleware to your route. It populates req.file or req.files, making access trivial.
import express from 'express';
import multer from 'multer';
import path from 'path';
const app = express();
// Configure disk storage
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, 'uploads/'),
filename: (req, file, cb) => cb(null, `${Date.now()}-${file.originalname}`)
});
const upload = multer({ storage });
app.post('/upload', upload.single('avatar'), (req, res) => {
// File is saved automatically, info available in req.file
res.json({
filename: req.file.filename,
path: req.file.path
});
});
formidable: The Standalone Powerhouseformidable works well with raw Node.js servers or frameworks like Koa. It uses a callback or promise-based API to parse the form and save files. It automatically handles temporary file creation.
import { IncomingForm } from 'formidable';
import { createServer } from 'node:http';
const server = createServer(async (req, res) => {
if (req.url === '/upload' && req.method.toLowerCase() === 'post') {
const form = new IncomingForm();
// Parse the form
const [fields, files] = await form.parse(req);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
uploadedFile: files.photo[0].originalFilename,
newPath: files.photo[0].filepath
}));
}
});
server.listen(3000);
@fastify/multipart: The Modern Async ApproachFor Fastify users, this plugin provides a clean, async interface. It allows you to iterate over parts of the request or access specific files directly, leveraging Fastify's schema validation and error handling.
import Fastify from 'fastify';
import multipart from '@fastify/multipart';
const fastify = Fastify();
await fastify.register(multipart);
fastify.post('/upload', async (request, reply) => {
const data = await request.file();
if (!data) {
reply.code(400).send({ error: 'No file uploaded' });
return;
}
// Save to disk using provided utility or pipe manually
await data.toBuffer(); // Or data.toFile('./uploads')
reply.send({
filename: data.filename,
type: data.mimetype
});
});
When dealing with large files (hundreds of MBs or GBs), memory management becomes critical.
busboy is the most memory-efficient. Since it streams data, your server's RAM usage stays flat regardless of file size. You are responsible for piping the stream to a destination that can handle the load.multer can be configured for streaming, but its default diskStorage writes to the filesystem efficiently. However, if you use memoryStorage, you risk crashing your server if a user uploads a file larger than your available RAM.formidable automatically writes to temporary files on disk, preventing memory bloat. It is safe for large uploads but involves disk I/O overhead.@fastify/multipart inherits busboy's streaming efficiency. It allows you to process data chunk-by-chunk without buffering the whole file, making it ideal for high-throughput microservices.Security is paramount when accepting user files. All libraries provide hooks for validation, but the implementation differs.
multer has a fileFilter option to reject files based on MIME type or extension. It is straightforward but relies on the client-sent MIME type, which can be spoofed. You should add a second layer of validation (e.g., checking file magic numbers) after upload.const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(new Error('Only PNG images are allowed'), false);
}
};
const upload = multer({ fileFilter });
busboy requires you to manually check the mimeType in the file event. Because it is low-level, you must implement your own logic to abort the stream if the file type is invalid.busboy.on('file', (name, file, info) => {
if (info.mimeType !== 'image/png') {
file.resume(); // Discard data
return;
}
// Process valid file
});
formidable allows setting maxFileSize and filter functions to validate incoming files before they are fully written.const form = new IncomingForm({
maxFileSize: 10 * 1024 * 1024, // 10MB limit
filter: ({ mimetype }) => mimetype === 'image/png'
});
@fastify/multipart integrates with Fastify's schema validation. You can define limits in the plugin options and validate MIME types using hooks or schemas before processing the file.await fastify.register(multipart, {
limits: { fileSize: 10 * 1024 * 1024 },
throwFileSizeLimit: true
});
How each library reports errors affects how you structure your try/catch blocks.
multer passes errors to the Express next(err) middleware. You need a specific error handling middleware to catch MulterError instances.busboy emits error events. If you don't attach an error listener, your application might crash on malformed requests.formidable rejects the promise or calls the error callback, making it easy to wrap in a standard try/catch block.@fastify/multipart throws standard JavaScript errors that Fastify can catch and serialize automatically according to your error handler configuration.| Feature | busboy | multer | formidable | @fastify/multipart |
|---|---|---|---|---|
| Primary Use Case | Custom streams, S3 direct upload | Express.js apps | Raw HTTP, Koa, Hono | Fastify apps |
| Learning Curve | High (Manual stream handling) | Low (Convention based) | Medium | Low (Async/Await) |
| File Storage | Manual (You pipe it) | Automatic (Disk/Memory) | Automatic (Temp Disk) | Manual or Utility helpers |
| Performance | ⭐⭐⭐⭐⭐ (Pure Stream) | ⭐⭐⭐⭐ (Efficient) | ⭐⭐⭐ (Disk I/O) | ⭐⭐⭐⭐⭐ (Stream based) |
| Framework Integration | None (Generic) | Express Only | Generic / Koa | Fastify Only |
If you are using Express, stick with multer. The ecosystem support, middleware compatibility, and simplicity make it the right tool for the job. Trying to force busboy into Express often leads to reinventing what multer already does well.
If you are using Fastify, @fastify/multipart is the only logical choice. It respects the framework's performance goals and async architecture. Using multer with Fastify is possible but discouraged as it bypasses Fastify's lifecycle optimizations.
For custom servers, Koa, or Hono, formidable offers the best balance of ease-of-use and reliability. It handles the messy details of multipart parsing so you can focus on business logic.
Finally, reach for busboy directly only if you have very specific needs—such as piping uploads directly to a cloud bucket without saving to disk first, or if you are building a library that needs to minimize dependencies. For most application-level code, the higher-level wrappers provide better safety and developer experience.
Choose formidable if you are working with raw Node.js http servers, Koa, or Hono, and need a reliable, feature-rich parser that handles file saving automatically. It is excellent for prototypes and applications where developer experience and straightforward configuration are more important than squeezing out every millisecond of performance. It is less suitable for Express apps where multer is the convention.
Choose @fastify/multipart if you are building an application with the Fastify framework. It is the only choice that fully integrates with Fastify's lifecycle, schema validation, and error handling. It is ideal for high-performance APIs where you need to process streams efficiently using async/await syntax without the overhead of callback-based middleware.
Choose busboy if you need maximum control over the parsing process or are building a custom framework. It is a streaming parser that does not save files for you, so it is best suited for scenarios where you need to pipe data directly to cloud storage (like S3) or perform custom validation on every chunk. Avoid it for simple projects unless you need to minimize dependencies or require specific stream manipulation.
Choose multer if your project is built on Express.js. It is the community standard for this framework, offering extensive documentation, plugins, and middleware compatibility. It is the best fit for traditional server-rendered apps or REST APIs where files need to be stored locally on the server disk or in memory before further processing. Do not use it with Fastify or non-Express frameworks.
A Node.js module for parsing form data, especially file uploads.
If you have any how-to kind of questions, please read the Contributing
Guide and Code of Conduct
documents.
For bugs reports and feature requests, please create an
issue or ping @wgw_eth / @wgw_lol
at Twitter.
This project is semantically versioned and if you want support in migrating between versions you can schedule us for training or support us through donations, so we can prioritize.
[!CAUTION] As of April 2025, old versions like v1 and v2 are still the most used, while they are deperecated for years -- they are also vulnerable to attacks if you are not implementing it properly. Please upgrade! We are here to help, and AI Editors & Agents could help a lot in such codemod-like migrations.
[!TIP] If you are starting a fresh project, you can check out the
formidable-miniwhich is a super minimal version of Formidable (not quite configurable yet, but when it does it could become the basis forformidable@v4), using web standards like FormData API and File API, and you can use it to stream uploads directly to S3 or other such services.
[!NOTE] Check VERSION NOTES for more information on v1, v2, and v3 plans, NPM dist-tags and branches._
This module was initially developed by @felixge for Transloadit, a service focused on uploading and encoding images and videos. It has been battle-tested against hundreds of GBs of file uploads from a large variety of clients and is considered production-ready and is used in production for years.
Currently, we are few maintainers trying to deal with it. :) More contributors are always welcome! :heart: Jump on issue #412 which is closed, but if you are interested we can discuss it and add you after strict rules, like enabling Two-Factor Auth in your npm and GitHub accounts.
options.fileWriteStreamHandler)This package is a dual ESM/commonjs package.
[!NOTE] This project requires
Node.js >= 20. Install it using yarn or npm.
We highly recommend to use Yarn when you think to contribute to this project.
This is a low-level package, and if you're using a high-level framework it may already be included. Check the examples below and the examples/ folder.
# v2
npm install formidable@v2
# v3
npm install formidable
npm install formidable@v3
Note: Future not ready releases will be published on *-next dist-tags for the corresponding version.
For more examples look at the examples/ directory.
Parse an incoming file upload, with the
Node.js's built-in http module.
import http from 'node:http';
import formidable, {errors as formidableErrors} from 'formidable';
const server = http.createServer(async (req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({});
let fields;
let files;
try {
[fields, files] = await form.parse(req);
} catch (err) {
// example to check for a very specific error
if (err.code === formidableErrors.maxFieldsExceeded) {
}
console.error(err);
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ fields, files }, null, 2));
return;
}
// show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="multipleFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
server.listen(8080, () => {
console.log('Server listening on http://localhost:8080/ ...');
});
There are multiple variants to do this, but Formidable just need Node.js Request stream, so something like the following example should work just fine, without any third-party Express.js middleware.
Or try the examples/with-express.js
import express from 'express';
import formidable from 'formidable';
const app = express();
app.get('/', (req, res) => {
res.send(`
<h2>With <code>"express"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
app.post('/api/upload', (req, res, next) => {
const form = formidable({});
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
Of course, with Koa v1, v2 or future v3 the things
are very similar. You can use formidable manually as shown below or through
the koa-better-body package which is
using formidable under the hood and support more features and different
request bodies, check its documentation for more info.
Note: this example is assuming Koa v2. Be aware that you should pass ctx.req
which is Node.js's Request, and NOT the ctx.request which is Koa's Request
object - there is a difference.
import Koa from 'Koa';
import formidable from 'formidable';
const app = new Koa();
app.on('error', (err) => {
console.error('server error', err);
});
app.use(async (ctx, next) => {
if (ctx.url === '/api/upload' && ctx.method.toLowerCase() === 'post') {
const form = formidable({});
// not very elegant, but that's for now if you don't want to use `koa-better-body`
// or other middlewares.
await new Promise((resolve, reject) => {
form.parse(ctx.req, (err, fields, files) => {
if (err) {
reject(err);
return;
}
ctx.set('Content-Type', 'application/json');
ctx.status = 200;
ctx.state = { fields, files };
ctx.body = JSON.stringify(ctx.state, null, 2);
resolve();
});
});
await next();
return;
}
// show a file upload form
ctx.set('Content-Type', 'text/html');
ctx.status = 200;
ctx.body = `
<h2>With <code>"koa"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="koaFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`;
});
app.use((ctx) => {
console.log('The next middleware is called');
console.log('Results:', ctx.state);
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
The benchmark is quite old, from the old codebase. But maybe quite true though. Previously the numbers was around ~500 mb/sec. Currently with moving to the new Node.js Streams API it's faster. You can clearly see the differences between the Node versions.
Note: a lot better benchmarking could and should be done in future.
Benchmarked on 8GB RAM, Xeon X3440 (2.53 GHz, 4 cores, 8 threads)
~/github/node-formidable master
❯ nve --parallel 8 10 12 13 node benchmark/bench-multipart-parser.js
⬢ Node 8
1261.08 mb/sec
⬢ Node 10
1113.04 mb/sec
⬢ Node 12
2107.00 mb/sec
⬢ Node 13
2566.42 mb/sec

All shown are equivalent.
Please pass options to the function/constructor, not by assigning
them to the instance form
import formidable from 'formidable';
const form = formidable(options);
See it's defaults in src/Formidable.js DEFAULT_OPTIONS
(the DEFAULT_OPTIONS constant).
options.encoding {string} - default 'utf-8'; sets encoding for
incoming form fields,
options.uploadDir {string} - default os.tmpdir(); the directory for
placing file uploads in. You can move them later by using fs.rename().
options.keepExtensions {boolean} - default false; to include the
extensions of the original files or not
options.allowEmptyFiles {boolean} - default false; allow upload empty
files
options.minFileSize {number} - default 1 (1byte); the minium size of
uploaded file.
options.maxFiles {number} - default Infinity;
limit the amount of uploaded files, set Infinity for unlimited
options.maxFileSize {number} - default 200 * 1024 * 1024 (200mb);
limit the size of each uploaded file.
options.maxTotalFileSize {number} - default options.maxFileSize;
limit the size of the batch of uploaded files.
options.maxFields {number} - default 1000; limit the number of fields, set Infinity for unlimited
options.maxFieldsSize {number} - default 20 * 1024 * 1024 (20mb);
limit the amount of memory all fields together (except files) can allocate in
bytes.
options.hashAlgorithm {string | false} - default false; include checksums calculated
for incoming files, set this to some hash algorithm, see
crypto.createHash
for available algorithms
options.fileWriteStreamHandler {function} - default null, which by
default writes to host machine file system every file parsed; The function
should return an instance of a
Writable stream
that will receive the uploaded file data. With this option, you can have any
custom behavior regarding where the uploaded file data will be streamed for.
If you are looking to write the file uploaded in other types of cloud storages
(AWS S3, Azure blob storage, Google cloud storage) or private file storage,
this is the option you're looking for. When this option is defined the default
behavior of writing the file in the host machine file system is lost.
options.filename {function} - default undefined Use it to control
newFilename. Must return a string. Will be joined with options.uploadDir.
options.filter {function} - default function that always returns true.
Use it to filter files before they are uploaded. Must return a boolean. Will not make the form.parse error
options.createDirsFromUploads {boolean} - default false. If true, makes direct folder uploads possible. Use <input type="file" name="folders" webkitdirectory directory multiple> to create a form to upload folders. Has to be used with the options options.uploadDir and options.filename where options.filename has to return a string with the character / for folders to be created. The base will be options.uploadDir.
options.filename {function} function (name, ext, part, form) -> stringwhere part can be decomposed as
const { originalFilename, mimetype} = part;
Note: If this size of combined fields, or size of some file is exceeded, an
'error' event is fired.
// The amount of bytes received for this form so far.
form.bytesReceived;
// The expected number of bytes in this form.
form.bytesExpected;
options.filter {function} function ({name, originalFilename, mimetype}) -> booleanBehaves like Array.filter: Returning false will simply ignore the file and go to the next.
const options = {
filter: function ({name, originalFilename, mimetype}) {
// keep only images
return mimetype && mimetype.includes("image");
}
};
Note: use an outside variable to cancel all uploads upon the first error
Note: use form.emit('error') to make form.parse error
let cancelUploads = false;// create variable at the same scope as form
const options = {
filter: function ({name, originalFilename, mimetype}) {
// keep only images
const valid = mimetype && mimetype.includes("image");
if (!valid) {
form.emit('error', new formidableErrors.default('invalid type', 0, 400)); // optional make form.parse error
cancelUploads = true; //variable to make filter return false after the first problem
}
return valid && !cancelUploads;
}
};
Parses an incoming Node.js request containing form data. If callback is not provided a promise is returned.
const form = formidable({ uploadDir: __dirname });
form.parse(req, (err, fields, files) => {
console.log('fields:', fields);
console.log('files:', files);
});
// with Promise
const [fields, files] = await form.parse(req);
You may overwrite this method if you are interested in directly accessing the
multipart stream. Doing so will disable any 'field' / 'file' events
processing which would occur otherwise, making you fully responsible for
handling the processing.
About uploadDir, given the following directory structure
project-name
├── src
│ └── server.js
│
└── uploads
└── image.jpg
__dirname would be the same directory as the source file itself (src)
`${__dirname}/../uploads`
to put files in uploads.
Omitting __dirname would make the path relative to the current working directory. This would be the same if server.js is launched from src but not project-name.
null will use default which is os.tmpdir()
Note: If the directory does not exist, the uploaded files are silently discarded. To make sure it exists:
import {createNecessaryDirectoriesSync} from "filesac";
const uploadPath = `${__dirname}/../uploads`;
createNecessaryDirectoriesSync(`${uploadPath}/x`);
In the example below, we listen on couple of events and direct them to the
data listener, so you can do whatever you choose there, based on whether its
before the file been emitted, the header value, the header name, on field, on
file and etc.
Or the other way could be to just override the form.onPart as it's shown a bit
later.
form.once('error', console.error);
form.on('fileBegin', (formname, file) => {
form.emit('data', { name: 'fileBegin', formname, value: file });
});
form.on('file', (formname, file) => {
form.emit('data', { name: 'file', formname, value: file });
});
form.on('field', (fieldName, fieldValue) => {
form.emit('data', { name: 'field', key: fieldName, value: fieldValue });
});
form.once('end', () => {
console.log('Done!');
});
// If you want to customize whatever you want...
form.on('data', ({ name, key, value, buffer, start, end, formname, ...more }) => {
if (name === 'partBegin') {
}
if (name === 'partData') {
}
if (name === 'headerField') {
}
if (name === 'headerValue') {
}
if (name === 'headerEnd') {
}
if (name === 'headersEnd') {
}
if (name === 'field') {
console.log('field name:', key);
console.log('field value:', value);
}
if (name === 'file') {
console.log('file:', formname, value);
}
if (name === 'fileBegin') {
console.log('fileBegin:', formname, value);
}
});
A method that allows you to extend the Formidable library. By default we include 4 plugins, which essentially are adapters to plug the different built-in parsers.
The plugins added by this method are always enabled.
See src/plugins/ for more detailed look on default plugins.
The plugin param has such signature:
function(formidable: Formidable, options: Options): void;
The architecture is simple. The plugin is a function that is passed with the
Formidable instance (the form across the README examples) and the options.
Note: the plugin function's this context is also the same instance.
const form = formidable({ keepExtensions: true });
form.use((self, options) => {
// self === this === form
console.log('woohoo, custom plugin');
// do your stuff; check `src/plugins` for inspiration
});
form.parse(req, (error, fields, files) => {
console.log('done!');
});
Important to note, is that inside plugin this.options, self.options and
options MAY or MAY NOT be the same. General best practice is to always use the
this, so you can later test your plugin independently and more easily.
If you want to disable some parsing capabilities of Formidable, you can disable
the plugin which corresponds to the parser. For example, if you want to disable
multipart parsing (so the src/parsers/Multipart.js
which is used in src/plugins/multipart.js), then
you can remove it from the options.enabledPlugins, like so
import formidable, {octetstream, querystring, json} from "formidable";
const form = formidable({
hashAlgorithm: 'sha1',
enabledPlugins: [octetstream, querystring, json],
});
Be aware that the order MAY be important too. The names corresponds 1:1 to files in src/plugins/ folder.
Pull requests for new built-in plugins MAY be accepted - for example, more
advanced querystring parser. Add your plugin as a new file in src/plugins/
folder (lowercased) and follow how the other plugins are made.
If you want to use Formidable to only handle certain parts for you, you can do something similar. Or see #387 for inspiration, you can for example validate the mime-type.
const form = formidable();
form.onPart = (part) => {
part.on('data', (buffer) => {
// do whatever you want here
});
};
For example, force Formidable to be used only on non-file "parts" (i.e., html fields)
const form = formidable();
form.onPart = function (part) {
// let formidable handle only non-file parts
if (part.originalFilename === '' || !part.mimetype) {
// used internally, please do not override!
form._handlePart(part);
}
};
export interface File {
// The size of the uploaded file in bytes.
// If the file is still being uploaded (see `'fileBegin'` event),
// this property says how many bytes of the file have been written to disk yet.
file.size: number;
// The path this file is being written to. You can modify this in the `'fileBegin'` event in
// case you are unhappy with the way formidable generates a temporary path for your files.
file.filepath: string;
// The name this file had according to the uploading client.
file.originalFilename: string | null;
// calculated based on options provided
file.newFilename: string | null;
// The mime type of this file, according to the uploading client.
file.mimetype: string | null;
// A Date object (or `null`) containing the time this file was last written to.
// Mostly here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
file.mtime: Date | null;
file.hashAlgorithm: false | |'sha1' | 'md5' | 'sha256'
// If `options.hashAlgorithm` calculation was set, you can read the hex digest out of this var (at the end it will be a string)
file.hash: string | object | null;
}
This method returns a JSON-representation of the file, allowing you to
JSON.stringify() the file which is useful for logging and responding to
requests.
'progress'Emitted after each incoming chunk of data that has been parsed. Can be used to
roll your own progress bar. Warning Use this only for server side progress bar. On the client side better use XMLHttpRequest with xhr.upload.onprogress =
form.on('progress', (bytesReceived, bytesExpected) => {});
'field'Emitted whenever a field / value pair has been received.
form.on('field', (name, value) => {});
'fileBegin'Emitted whenever a new file is detected in the upload stream. Use this event if you want to stream the file to somewhere else while buffering the upload on the file system.
form.on('fileBegin', (formName, file) => {
// accessible here
// formName the name in the form (<input name="thisname" type="file">) or http filename for octetstream
// file.originalFilename http filename or null if there was a parsing error
// file.newFilename generated hexoid or what options.filename returned
// file.filepath default pathname as per options.uploadDir and options.filename
// file.filepath = CUSTOM_PATH // to change the final path
});
'file'Emitted whenever a field / file pair has been received. file is an instance of
File.
form.on('file', (formname, file) => {
// same as fileBegin, except
// it is too late to change file.filepath
// file.hash is available if options.hash was used
});
'error'Emitted when there is an error processing the incoming form. A request that
experiences an error is automatically paused, you will have to manually call
request.resume() if you want the request to continue firing 'data' events.
May have error.httpCode and error.code attached.
form.on('error', (err) => {});
'aborted'Emitted when the request was aborted by the user. Right now this can be due to a
'timeout' or 'close' event on the socket. After this event is emitted, an
error event will follow. In the future there will be a separate 'timeout'
event (needs a change in the node core).
form.on('aborted', () => {});
'end'Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.
form.on('end', () => {});
Gets first values of fields, like pre 3.0.0 without multiples pass in a list of optional exceptions where arrays of strings is still wanted (<select multiple> for example)
import { firstValues } from 'formidable/src/helpers/firstValues.js';
// ...
form.parse(request, async (error, fieldsMultiple, files) => {
if (error) {
//...
}
const exceptions = ['thisshouldbeanarray'];
const fieldsSingle = firstValues(form, fieldsMultiple, exceptions);
// ...
Html form input type="checkbox" only send the value "on" if checked, convert it to booleans for each input that is expected to be sent as a checkbox, only use after firstValues or similar was called.
import { firstValues } from 'formidable/src/helpers/firstValues.js';
import { readBooleans } from 'formidable/src/helpers/readBooleans.js';
// ...
form.parse(request, async (error, fieldsMultiple, files) => {
if (error) {
//...
}
const fieldsSingle = firstValues(form, fieldsMultiple);
const expectedBooleans = ['checkbox1', 'wantsNewsLetter', 'hasACar'];
const fieldsWithBooleans = readBooleans(fieldsSingle, expectedBooleans);
// ...
multipart_parser.js.If the documentation is unclear or has a typo, please click on the page's Edit
button (pencil icon) and suggest a correction. If you would like to help us fix
a bug or add a new feature, please check our Contributing
Guide. Pull requests are welcome!
Thanks goes to these wonderful people (emoji key):
From a Felix blog post:
Formidable is licensed under the MIT License.