### Install Formidable v2 and v3
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Instructions for installing specific versions of the formidable package using npm.
```bash
npm install formidable@v2
```
```bash
npm install formidable
npm install formidable@v3
```
--------------------------------
### Check Node.js Version
Source: https://github.com/node-formidable/formidable/blob/master/benchmark/2022-11-30-i5-9600k.txt
Verify the installed Node.js version. This is useful for ensuring compatibility and tracking performance differences across versions.
```bash
node -v
```
--------------------------------
### Parse Request with Formidable (Callback-based)
Source: https://context7.com/node-formidable/formidable/llms.txt
This is a commented-out example demonstrating the callback-based approach for parsing requests with Formidable. It's an alternative to the Promise-based method shown in the main example.
```javascript
// const form2 = formidable({});
// form2.parse(req, (err, fields, files) => {
// if (err) { next(err); return; }
// res.json({ fields, files });
// });
```
--------------------------------
### Handle Formidable Events
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Listen to various formidable events like 'fileBegin', 'file', and 'field' to process data as it arrives. This example emits custom 'data' events for centralized handling.
```javascript
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);
}
}
);
```
--------------------------------
### Parse File Upload with Koa
Source: https://github.com/node-formidable/formidable/blob/master/README.md
This example demonstrates how to use Formidable with Koa. It requires passing `ctx.req` (Node.js's Request object) to `form.parse`. The snippet includes handling the upload and serving an HTML form.
```javascript
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 =
`
With "koa" npm package
`;
});
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 ...");
});
```
--------------------------------
### Parse Request with Callback
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Use the `form.parse` method to process incoming request data. This example shows the callback-based approach, logging fields and files.
```javascript
const form = formidable({ uploadDir: __dirname });
form.parse(req, (err, fields, files) => {
console.log("fields:", fields);
console.log("files:", files);
});
```
--------------------------------
### Handle Specific Parts with onPart
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Override the `onPart` method to selectively process incoming parts. This example shows how to let Formidable handle only non-file parts.
```javascript
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);
}
};
```
--------------------------------
### Parse File Upload with Express.js
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Integrate Formidable with Express.js to handle file uploads. This example shows how to set up a route for serving an upload form and another for processing the uploaded files.
```javascript
import express from "express";
import formidable from "formidable";
const app = express();
app.get("/", (req, res) => {
res.send(
`
With "express" npm package
`
);
});
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 ...");
});
```
--------------------------------
### Intercept Raw Multipart Parts with onPart
Source: https://context7.com/node-formidable/formidable/llms.txt
Override `form.onPart` to manually handle specific multipart parts. Call `form._handlePart(part)` for parts that should be processed by Formidable normally. This example only lets Formidable handle text fields.
```javascript
import http from 'node:http';
import formidable from 'formidable';
const server = http.createServer((req, res) => {
const form = formidable();
// Only let Formidable handle text fields; handle files manually
form.onPart = (part) => {
if (!part.originalFilename && !part.mimetype) {
// It's a text field — let formidable handle it normally
form._handlePart(part);
return;
}
// It's a file — handle it ourselves (e.g. discard or inspect)
console.log(`Intercepted file part: ${part.originalFilename}`);
part.on('data', (buffer) => {
console.log(` chunk: ${buffer.length} bytes`);
});
part.on('end', () => {
console.log(` done: ${part.originalFilename}`);
});
};
form.parse(req, (err, fields) => {
if (err) { res.writeHead(400).end(err.message); return; }
res.end(JSON.stringify({ fields }));
});
});
server.listen(8080);
```
--------------------------------
### Get First Values of Fields with Exceptions
Source: https://github.com/node-formidable/formidable/blob/master/README.md
The `firstValues` helper retrieves the first value for each field, similar to pre-3.0.0 behavior. It accepts an optional list of exceptions where arrays of strings should still be preserved, such as for multi-select inputs.
```javascript
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);
// ...
});
```
--------------------------------
### Initialize Formidable with Options
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Instantiate the Formidable parser with custom options. Pass options to the constructor, not by assigning them to the instance.
```javascript
import formidable from "formidable";
const form = formidable(options);
```
--------------------------------
### Formidable Initialization
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Instantiate Formidable with options to configure its behavior for parsing incoming form data and handling file uploads.
```APIDOC
## Formidable / IncomingForm
All shown are equivalent.
_Please pass [`options`](#options) to the function/constructor, not by assigning
them to the instance `form`_
```js
import formidable from "formidable";
const form = formidable(options);
```
```
--------------------------------
### Event: 'fileBegin'
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Emitted when a new file is detected. Useful for streaming files to alternative locations while Formidable buffers them.
```APIDOC
## Event: 'fileBegin'
### Description
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.
### Parameters
- **formName** (string) - The name of the form field or http filename for octetstream.
- **file** (object) - An object containing file details:
- **originalFilename** (string | null) - The original filename or null if there was a parsing error.
- **newFilename** (string) - The generated filename (hexoid or from options.filename).
- **filepath** (string) - The default path for saving the file, based on options.uploadDir and options.filename. This can be modified before the file is written.
### Example
```js
form.on("fileBegin", (formName, file) => {
// formName: the name in the form () 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
});
```
```
--------------------------------
### Formidable Options Configuration
Source: https://context7.com/node-formidable/formidable/llms.txt
Configure Formidable instance with various options for encoding, upload directories, file size limits, and more. All options are passed during instance creation.
```javascript
import formidable from 'formidable';
// All available options with their defaults
const form = formidable({
encoding: 'utf-8',
// encoding for incoming form fields
uploadDir: os.tmpdir(), // directory for file uploads
keepExtensions: false, // preserve original file extensions
allowEmptyFiles: false, // allow zero-byte file uploads
minFileSize: 1, // minimum file size in bytes
maxFiles: 1000, // maximum number of files per request
maxFileSize: 200 * 1024 * 1024, // 200 MB per file
maxTotalFileSize: undefined, // defaults to maxFileSize
maxFields: 1000, // maximum number of non-file fields
maxFieldsSize: 20 * 1024 * 1024,// 20 MB total for all fields
hashAlgorithm: false, // e.g. 'sha256', 'md5' — false to disable
fileWriteStreamHandler: null, // custom writable stream factory (for S3 etc.)
createDirsFromUploads: false, // create subdirectories from uploaded folder structure
filter: ({ name, originalFilename, mimetype }) => true, // return false to skip a file
filename: undefined, // custom filename function (name, ext, part, form) => string
});
```
--------------------------------
### Run Formidable Benchmark
Source: https://github.com/node-formidable/formidable/blob/master/benchmark/2022-11-30-i5-9600k.txt
Execute the benchmark script for the Formidable library. This command is used to measure performance.
```bash
npm run bench
```
--------------------------------
### Handle New File Uploads with formidable
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Use the 'fileBegin' event to detect new file uploads. This is useful for streaming files to other locations while buffering them on the file system. You can access form name, original filename, generated filename, and filepath.
```javascript
form.on("fileBegin", (formName, file) => {
// accessible here
// formName the name in the form () 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
});
```
--------------------------------
### formidable(options)
Source: https://context7.com/node-formidable/formidable/llms.txt
Creates a new Formidable (IncomingForm) instance with the specified options. All configuration should be passed during instantiation.
```APIDOC
## formidable(options) — Create a form parser instance
The default export is a factory function that returns a `Formidable` (also known as `IncomingForm`) instance. All configuration is passed as `options` to this factory; do not assign options to the instance after creation. The instance is an `EventEmitter` and supports both callback and Promise-based parsing.
```js
import formidable from 'formidable';
// All available options with their defaults
const form = formidable({
encoding: 'utf-8', // encoding for incoming form fields
uploadDir: os.tmpdir(), // directory for file uploads
keepExtensions: false, // preserve original file extensions
allowEmptyFiles: false, // allow zero-byte file uploads
minFileSize: 1, // minimum file size in bytes
maxFiles: 1000, // maximum number of files per request
maxFileSize: 200 * 1024 * 1024, // 200 MB per file
maxTotalFileSize: undefined, // defaults to maxFileSize
maxFields: 1000, // maximum number of non-file fields
maxFieldsSize: 20 * 1024 * 1024,// 20 MB total for all fields
hashAlgorithm: false, // e.g. 'sha256', 'md5' — false to disable
fileWriteStreamHandler: null, // custom writable stream factory (for S3 etc.)
createDirsFromUploads: false, // create subdirectories from uploaded folder structure
filter: ({ name, originalFilename, mimetype }) => true, // return false to skip a file
filename: undefined, // custom filename function (name, ext, part, form) => string
});
```
```
--------------------------------
### Handle Formidable Errors with Typed Error Codes
Source: https://context7.com/node-formidable/formidable/llms.txt
Use Formidable's typed error codes for precise error handling in asynchronous operations. This example demonstrates handling common errors like exceeding file size limits or too many fields. Ensure the server is listening on port 8080.
```javascript
import formidable, { errors as formidableErrors } from 'formidable';
import http from 'node:http';
const server = http.createServer(async (req, res) => {
const form = formidable({ maxFileSize: 1024 * 1024 }); // 1 MB limit
try {
const [fields, files] = await form.parse(req);
res.end(JSON.stringify({ fields, files }));
} catch (err) {
// err.code matches a numeric constant from formidableErrors
switch (err.code) {
case formidableErrors.biggerThanMaxFileSize: // 1016
res.writeHead(413).end('File exceeds 1 MB limit');
break;
case formidableErrors.biggerThanTotalMaxFileSize: // 1009
res.writeHead(413).end('Total upload size exceeded');
break;
case formidableErrors.maxFieldsExceeded: // 1007
res.writeHead(413).end('Too many fields');
break;
case formidableErrors.maxFilesExceeded: // 1015
res.writeHead(413).end('Too many files');
break;
case formidableErrors.missingContentType: // 1011
res.writeHead(400).end('Missing Content-Type header');
break;
case formidableErrors.aborted: // 1002
res.writeHead(400).end('Request aborted');
break;
default:
res.writeHead(err.httpCode || 500).end(err.message);
}
}
});
server.listen(8080);
```
--------------------------------
### Formidable Options
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Configure Formidable's behavior by passing an options object during initialization. These options control aspects like encoding, upload directories, file size limits, and more.
```APIDOC
## Options
See it's defaults in [src/Formidable.js DEFAULT_OPTIONS](./src/Formidable.js)
(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](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options)
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](https://nodejs.org/api/stream.html#stream_class_stream_writable)
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 `` 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) -> string
where part can be decomposed as
```js
const { originalFilename, mimetype } = part;
```
_**Note:** If this size of combined fields, or size of some file is exceeded,
an
`'error'` event is fired._
```js
// The amount of bytes received for this form so far.
form.bytesReceived;
```
```js
// The expected number of bytes in this form.
form.bytesExpected;
```
```
--------------------------------
### Parse Request with Promise
Source: https://github.com/node-formidable/formidable/blob/master/README.md
An alternative to the callback method, this demonstrates parsing a request using Promises and `async/await` syntax for cleaner asynchronous code.
```javascript
// with Promise
const [fields, files] = await form.parse(req);
```
--------------------------------
### Configure Enabled Plugins
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Initialize Formidable with specific plugins enabled by passing an array to `enabledPlugins`. This allows disabling default parsers like multipart.
```javascript
import formidable, { octetstream, querystring, json } from "formidable";
const form = formidable({
hashAlgorithm: "sha1",
enabledPlugins: [octetstream, querystring, json],
});
```
--------------------------------
### Register and Use a Custom Plugin
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Instantiate Formidable and then use the `.use()` method to register a custom plugin function. The plugin can access the Formidable instance via `self` or `this`.
```javascript
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!");
});
```
--------------------------------
### Listen for Progress Events
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Use the `'progress'` event to monitor the upload progress. This event emits the number of bytes received and expected. Use this for server-side progress bars only.
```javascript
form.on("progress", (bytesReceived, bytesExpected) => {});
```
--------------------------------
### File Filtering with `options.filter`
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Configure a filter function to selectively process files based on their properties. Returning `false` will ignore the file.
```APIDOC
## options.filter
### Description
Behaves like `Array.filter`: Returning `false` will simply ignore the file and go to the next.
### Parameters
- **name** (string) - The name of the file.
- **originalFilename** (string) - The original filename.
- **mimetype** (string) - The MIME type of the file.
### Return Value
- **boolean**: `true` to keep the file, `false` to ignore it.
### Example
```javascript
const options = {
filter: function ({ name, originalFilename, mimetype }) {
// keep only images
return mimetype && mimetype.includes("image");
},
};
```
### Error Handling Example
```javascript
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;
},
};
```
```
--------------------------------
### Specify Upload Directory
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Configure the upload directory for formidable. Using `__dirname` makes the path relative to the current script, while omitting it uses the current working directory.
```javascript
"${__dirname}/../uploads";
```
--------------------------------
### Benchmark Results Across Node.js Versions
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Performance comparison of the multipart parser across Node.js 8, 10, 12, and 13. Results are measured in megabytes per second (mb/sec).
```bash
~/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
```
--------------------------------
### Ensure Upload Directories Exist
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Use `filesac` to synchronously create necessary directories for uploads. This prevents files from being silently discarded if the target directory is missing.
```javascript
import { createNecessaryDirectoriesSync } from "filesac";
const uploadPath = `${__dirname}/../uploads`;
createNecessaryDirectoriesSync(`${uploadPath}/x`);
```
--------------------------------
### .use(plugin: Plugin)
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Extends the Formidable library by allowing custom plugins to be added. These plugins can modify or extend the parsing capabilities of Formidable.
```APIDOC
## .use(plugin: Plugin)
### Description
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/](./src/plugins/) for more detailed look on default plugins.
The `plugin` param has such signature:
```typescript
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.
### Request Example
```js
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](./src/parsers/Multipart.js)
which is used in [src/plugins/multipart.js](./src/plugins/multipart.js)), then
you can remove it from the `options.enabledPlugins`, like so
### Request Example
```js
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/](./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.
```
--------------------------------
### form.parse with Express.js
Source: https://context7.com/node-formidable/formidable/llms.txt
Demonstrates how to use Formidable's `parse` method directly within an Express.js application without requiring special middleware.
```APIDOC
## `form.parse` with Express.js
Formidable works directly with Express by consuming the raw Node.js request stream (`req` from Express is a native `http.IncomingMessage`); no special middleware is required.
```js
import express from 'express';
import formidable from 'formidable';
const app = express();
app.post('/api/upload', (req, res, next) => {
const form = formidable({
uploadDir: '/tmp/uploads',
keepExtensions: true,
maxFiles: 5,
maxFileSize: 50 * 1024 * 1024, // 50 MB
});
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
// fields.title -> ['My Title']
// files.document -> [PersistentFile { ... }]
res.json({ fields, files });
});
});
app.listen(3000);
```
```
--------------------------------
### Custom File Naming with `options.filename`
Source: https://context7.com/node-formidable/formidable/llms.txt
Provide a synchronous function to `options.filename` to control how uploaded files are named on disk. The returned string is joined with `options.uploadDir`.
```javascript
import path from 'node:path';
import formidable from 'formidable';
import http from 'node:http';
const server = http.createServer(async (req, res) => {
let counter = 0;
const form = formidable({
uploadDir: '/tmp/uploads',
keepExtensions: true,
filename(name, ext, part, form) {
// name = base name without extension
// ext = extension including dot, e.g. '.jpg'
// part = { originalFilename, mimetype, ... }
counter += 1;
const safeName = name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
return `${Date.now()}_${counter}_${safeName}${ext}`;
// e.g. -> /tmp/uploads/1700000000000_1_photo.jpg
},
});
const [fields, files] = await form.parse(req);
res.end(JSON.stringify({ files }));
});
server.listen(8080);
```
--------------------------------
### form.parse with Koa
Source: https://context7.com/node-formidable/formidable/llms.txt
Demonstrates how to use `form.parse` with Koa, ensuring to pass `ctx.req` (the raw Node.js request) instead of `ctx.request` (the Koa request wrapper).
```APIDOC
## `form.parse` with Koa
When using Koa, pass `ctx.req` (the raw Node.js request), not `ctx.request` (the Koa request wrapper).
```js
import Koa from 'koa';
import formidable from 'formidable';
const app = new Koa();
app.use(async (ctx, next) => {
if (ctx.url === '/api/upload' && ctx.method.toLowerCase() === 'post') {
const form = formidable({ keepExtensions: true });
const [fields, files] = await new Promise((resolve, reject) => {
form.parse(ctx.req, (err, fields, files) => { // note: ctx.req, not ctx.request
if (err) reject(err);
else resolve([fields, files]);
});
});
ctx.status = 200;
ctx.set('Content-Type', 'application/json');
ctx.body = JSON.stringify({ fields, files }, null, 2);
await next();
}
});
app.listen(3000);
```
```
--------------------------------
### Process Received Files with formidable
Source: https://github.com/node-formidable/formidable/blob/master/README.md
The 'file' event is emitted when a field/file pair is received. It's too late to change the filepath at this point, but file.hash is available if options.hash was used.
```javascript
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
});
```
--------------------------------
### Compute File Checksums with hashAlgorithm
Source: https://context7.com/node-formidable/formidable/llms.txt
Set `hashAlgorithm` to compute file checksums. After parsing, `file.hash` will contain the hex digest. Supported algorithms are those of Node.js `crypto.createHash`.
```javascript
import http from 'node:http';
import formidable from 'formidable';
const server = http.createServer(async (req, res) => {
const form = formidable({
uploadDir: '/tmp/uploads',
hashAlgorithm: 'sha256',
});
const [fields, files] = await form.parse(req);
for (const [fieldName, fileList] of Object.entries(files)) {
for (const file of fileList) {
console.log(`${file.originalFilename}: sha256=${file.hash}`);
// e.g. photo.jpg: sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
}
}
res.end('ok');
});
server.listen(8080);
```
--------------------------------
### options.hashAlgorithm
Source: https://context7.com/node-formidable/formidable/llms.txt
Compute file checksums using Node.js crypto algorithms. The hex digest is stored in `file.hash` after parsing.
```APIDOC
## `options.hashAlgorithm` — Compute file checksums
Set `hashAlgorithm` to any algorithm supported by Node.js `crypto.createHash` (e.g. `'sha256'`, `'md5'`). After parsing, `file.hash` holds the hex digest.
```js
import http from 'node:http';
import formidable from 'formidable';
const server = http.createServer(async (req, res) => {
const form = formidable({
uploadDir: '/tmp/uploads',
hashAlgorithm: 'sha256',
});
const [fields, files] = await form.parse(req);
for (const [fieldName, fileList] of Object.entries(files)) {
for (const file of fileList) {
console.log(`${file.originalFilename}: sha256=${file.hash}`);
// e.g. photo.jpg: sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
}
}
res.end('ok');
});
server.listen(8080);
```
```
--------------------------------
### options.createDirsFromUploads
Source: https://context7.com/node-formidable/formidable/llms.txt
Preserve uploaded folder structure when `createDirsFromUploads` is true. This is useful for HTML inputs with the `webkitdirectory` attribute.
```APIDOC
## `options.createDirsFromUploads` — Preserve uploaded folder structure
When `createDirsFromUploads: true`, the `options.filename` function can return a path with `/` separators, and Formidable will create the required subdirectories under `uploadDir`. This is used in combination with `` HTML inputs.
```js
import path from 'node:path';
import formidable from 'formidable';
import http from 'node:http';
const BASE_UPLOAD_DIR = '/tmp/uploads';
const server = http.createServer(async (req, res) => {
const form = formidable({
uploadDir: BASE_UPLOAD_DIR,
createDirsFromUploads: true,
filename(name, ext, part) {
// originalFilename may be something like "myFolder/sub/file.txt"
// Return the relative path; formidable will create the directories
return part.originalFilename; // e.g. "project/src/index.js"
// Final path: /tmp/uploads/project/src/index.js
},
});
const [fields, files] = await form.parse(req);
res.end(JSON.stringify({ files }));
});
server.listen(8080);
```
```
--------------------------------
### Extend Formidable with Custom Plugins
Source: https://context7.com/node-formidable/formidable/llms.txt
Plugins extend Formidable's functionality. They are functions with the signature `(formidable, options) => void`. Built-in plugins can be selectively enabled or disabled via `options.enabledPlugins`.
```javascript
import formidable, { octetstream, querystring, json } from 'formidable';
import http from 'node:http';
// --- Disable multipart plugin (accept only JSON and urlencoded) ---
const form = formidable({
enabledPlugins: [querystring, json], // multipart and octetstream are excluded
});
// --- Add a custom plugin for logging ---
form.use((self, options) => {
self.on('fileBegin', (formname, file) => {
console.log(`[plugin] Starting upload: ${file.originalFilename}`);
});
self.on('file', (formname, file) => {
console.log(`[plugin] Finished: ${file.originalFilename} (${file.size} bytes)`);
});
});
const server = http.createServer(async (req, res) => {
try {
const [fields, files] = await form.parse(req);
res.end(JSON.stringify({ fields, files }));
} catch (err) {
res.writeHead(400).end(err.message);
}
});
server.listen(8080);
```
--------------------------------
### form.onPart
Source: https://context7.com/node-formidable/formidable/llms.txt
Intercept raw multipart parts to handle specific parts manually. Call `form._handlePart(part)` for parts that should be processed normally by Formidable.
```APIDOC
## `form.onPart` — Intercept raw multipart parts
Override `form.onPart` to handle specific parts manually. Call `form._handlePart(part)` for parts you want Formidable to process normally.
```js
import http from 'node:http';
import formidable from 'formidable';
const server = http.createServer((req, res) => {
const form = formidable();
// Only let Formidable handle text fields; handle files manually
form.onPart = (part) => {
if (!part.originalFilename && !part.mimetype) {
// It's a text field — let formidable handle it normally
form._handlePart(part);
return;
}
// It's a file — handle it ourselves (e.g. discard or inspect)
console.log(`Intercepted file part: ${part.originalFilename}`);
part.on('data', (buffer) => {
console.log(` chunk: ${buffer.length} bytes`);
});
part.on('end', () => {
console.log(` done: ${part.originalFilename}`);
});
};
form.parse(req, (err, fields) => {
if (err) { res.writeHead(400).end(err.message); return; }
res.end(JSON.stringify({ fields }));
});
});
server.listen(8080);
```
```
--------------------------------
### File Interface
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Defines the structure of a file object processed by Formidable, including properties like size, filepath, and original filename.
```APIDOC
## File Interface
```ts
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;
}
```
### file.toJSON()
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.
```
--------------------------------
### form.use(plugin)
Source: https://context7.com/node-formidable/formidable/llms.txt
Extend Formidable with custom plugins or selectively disable built-in plugins. Plugins are functions that modify Formidable's behavior.
```APIDOC
## `form.use(plugin)` — Extend Formidable with custom plugins
Plugins are functions with the signature `(formidable, options) => void` (or async). The four built-in plugins (`multipart`, `querystring`, `json`, `octetstream`) can be selectively disabled by passing a subset to `options.enabledPlugins`.
```js
import formidable, { octetstream, querystring, json } from 'formidable';
import http from 'node:http';
// --- Disable multipart plugin (accept only JSON and urlencoded) ---
const form = formidable({
enabledPlugins: [querystring, json], // multipart and octetstream are excluded
});
// --- Add a custom plugin for logging ---
form.use((self, options) => {
self.on('fileBegin', (formname, file) => {
console.log(`[plugin] Starting upload: ${file.originalFilename}`);
});
self.on('file', (formname, file) => {
console.log(`[plugin] Finished: ${file.originalFilename} (${file.size} bytes)`);
});
});
const server = http.createServer(async (req, res) => {
try {
const [fields, files] = await form.parse(req);
res.end(JSON.stringify({ fields, files }));
} catch (err) {
res.writeHead(400).end(err.message);
}
});
server.listen(8080);
```
```
--------------------------------
### Event: 'file'
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Emitted when a complete file/field pair has been received. The file path cannot be changed at this stage.
```APIDOC
## Event: 'file'
### Description
Emitted whenever a field / file pair has been received. `file` is an instance of `File`.
### Parameters
- **formname** (string) - The name of the form field.
- **file** (object) - An object containing file details (same properties as in 'fileBegin', but `filepath` cannot be changed).
- **hash** (string, optional) - Available if `options.hash` was used.
### Example
```js
form.on("file", (formname, file) => {
// It is too late to change file.filepath
// file.hash is available if options.hash was used
});
```
```
--------------------------------
### Event: 'end'
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Emitted when the entire request has been received and all files have been flushed to disk. Ideal for sending responses.
```APIDOC
## Event: 'end'
### Description
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.
### Example
```js
form.on("end", () => {});
```
```
--------------------------------
### API Load Testing with Bombardier
Source: https://github.com/node-formidable/formidable/blob/master/benchmark/2022-11-30-i5-9600k.txt
Use bombardier to perform load testing on a POST endpoint. This command simulates multiple connections and measures request statistics and throughput.
```bash
bombardier --body-file="./README.md" --method=POST
--duration=10s --connections=100 http://localhost:3000/api/upload
```
--------------------------------
### Add Custom Plugin to Formidable
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Use the `.use()` method to extend Formidable with custom functionality. The plugin function receives the Formidable instance and options.
```typescript
function(formidable: Formidable, options: Options): void;
```
--------------------------------
### Convert File to Base64 Request
Source: https://github.com/node-formidable/formidable/blob/master/test/tools/base64.html
Handles form submission by reading a file, encoding it to Base64, and making a request. Ensure the output is saved with Windows (CRLF) line endings.
```javascript
function form_submit(e) {
console.log(e);
var resultOutput = document.getElementById("resultOutput");
var fileInput = document.getElementById("fileInput");
var fieldInput = document.getElementById("fieldInput");
makeRequestBase64(fileInput.files[0], fieldInput.value, function ( err, result ) {
resultOutput.value = result;
});
return false;
}
function makeRequestBase64(file, fieldName, cb) {
var boundary = "\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/";
var crlf = "\r\n";
var reader = new FileReader();
reader.onload = function (e) {
var body = "";
body += "--" + boundary + crlf;
body += 'Content-Disposition: form-data; name="' + fieldName + '"; filename="' + escape(file.name) + '"' + crlf;
body += "Content-Type: " + file.type + "" + crlf;
body += "Content-Transfer-Encoding: base64" + crlf;
body += crlf;
body += e.target.result.substring(e.target.result.indexOf(",") + 1) + crlf;
body += "--" + boundary + "--";
var head = "";
head += "POST /upload HTTP/1.1" + crlf;
head += "Host: localhost:8080" + crlf;
head += "Content-Type: multipart/form-data; boundary=" + boundary + "" + crlf;
head += "Content-Length: " + body.length + "" + crlf;
cb(null, head + crlf + body);
};
reader.readAsDataURL(file);
}
```
--------------------------------
### Events
Source: https://github.com/node-formidable/formidable/blob/master/README.md
Details the events emitted by Formidable during the parsing process, such as 'progress', 'field', and 'fileBegin'.
```APIDOC
## Events
### '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 =`
### Request Example
```js
form.on("progress", (bytesReceived, bytesExpected) => {});
```
### 'field'
Emitted whenever a field / value pair has been received.
### Request Example
```js
form.on("field", (name, value) => {});
```
```