Socket
Socket
Sign inDemoInstall

formidable

Package Overview
Dependencies
4
Maintainers
5
Versions
78
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-dev.20200131.2 to 2.0.0

src/FormidableError.js

39

CHANGELOG.md

@@ -0,19 +1,24 @@

# Changelog
### Unreleased (`canary` & `dev` dist-tags)
* Test only on Node.js >= v10. Support only Node LTS and latest ([#515](https://github.com/node-formidable/node-formidable/pull/515))
* stop using deprecated features ([#516](https://github.com/node-formidable/node-formidable/pull/516), [#472](https://github.com/node-formidable/node-formidable/issues/472), [#406](https://github.com/node-formidable/node-formidable/issues/406))
* throw error during data parsing ([#513](https://github.com/node-formidable/node-formidable/pull/513))
* Array support for fields and files ([#380](https://github.com/node-formidable/node-formidable/pull/380), [#340](https://github.com/node-formidable/node-formidable/pull/340), [#367](https://github.com/node-formidable/node-formidable/pull/367), [#33](https://github.com/node-formidable/node-formidable/issues/33), [#498](https://github.com/node-formidable/node-formidable/issues/498), [#280](https://github.com/node-formidable/node-formidable/issues/280), [#483](https://github.com/node-formidable/node-formidable/issues/483))
* feat: add options.filter ([#716](https://github.com/node-formidable/formidable/pull/716))
* feat: add code and httpCode to most errors ([#686](https://github.com/node-formidable/formidable/pull/686))
* rename: option.hash into option.hashAlgorithm ([#689](https://github.com/node-formidable/formidable/pull/689))
* rename: file.path into file.filepath ([#689](https://github.com/node-formidable/formidable/pull/689))
* rename: file.type into file.mimetype ([#689](https://github.com/node-formidable/formidable/pull/689))
* refactor: split file.name into file.newFilename and file.originalFilename ([#689](https://github.com/node-formidable/formidable/pull/689))
* feat: prevent directory traversal attacks by default ([#689](https://github.com/node-formidable/formidable/pull/689))
* meta: stop including test files in npm ([7003c](https://github.com/node-formidable/formidable/commit/7003cd6133f90c384081accb51743688d5e1f4be))
* fix: handle invalid filenames ([d0a34](https://github.com/node-formidable/formidable/commit/d0a3484b048b8c177e62d66aecb03f5928f7a857))
* feat: add fileWriteStreamHandler option
* feat: add allowEmptyFiles and minFileSize options
* feat: Array support for fields and files ([#380](https://github.com/node-formidable/node-formidable/pull/380), [#340](https://github.com/node-formidable/node-formidable/pull/340), [#367](https://github.com/node-formidable/node-formidable/pull/367), [#33](https://github.com/node-formidable/node-formidable/issues/33), [#498](https://github.com/node-formidable/node-formidable/issues/498), [#280](https://github.com/node-formidable/node-formidable/issues/280), [#483](https://github.com/node-formidable/node-formidable/issues/483))
* possible partial fix of [#386](https://github.com/node-formidable/node-formidable/pull/386) with #380 (need tests and better implementation)
* use hasOwnProperty in check against files/fields ([#522](https://github.com/node-formidable/node-formidable/pull/522))
* do not promote `IncomingForm` and add `exports.default` ([#529](https://github.com/node-formidable/node-formidable/pull/529))
* Improve examples and tests ([#523](https://github.com/node-formidable/node-formidable/pull/523))
* First step of Code quality improvements ([#525](https://github.com/node-formidable/node-formidable/pull/525))
* refactor: use hasOwnProperty in check against files/fields ([#522](https://github.com/node-formidable/node-formidable/pull/522))
* meta: do not promote `IncomingForm` and add `exports.default` ([#529](https://github.com/node-formidable/node-formidable/pull/529))
* meta: Improve examples and tests ([#523](https://github.com/node-formidable/node-formidable/pull/523))
* refactor: First step of Code quality improvements ([#525](https://github.com/node-formidable/node-formidable/pull/525))
* chore(funding): remove patreon & add npm funding field ([#525](https://github.com/node-formidable/node-formidable/pull/532)
* feat: use Modern Streams API ([#531](https://github.com/node-formidable/node-formidable/pull/531))
* fix: remove gently hijack and tests ([#539](https://github.com/node-formidable/node-formidable/pull/539))
* docs: Clarify supported hash algorithms ([#537](https://github.com/node-formidable/node-formidable/pull/537))
* feat: better tests, add Airbnb + Prettier ([#542](https://github.com/node-formidable/node-formidable/pull/542))
* fix(incomingForm): better detection of fields vs files
* fix: resolves [#128](https://github.com/node-formidable/node-formidable/pull/128)
* fix: urlencoded parsing to emit end [#543](https://github.com/node-formidable/node-formidable/pull/543), introduced in [#531](https://github.com/node-formidable/node-formidable/pull/531)

@@ -24,5 +29,7 @@ * fix(tests): include multipart and qs parser unit tests, part of [#415](https://github.com/node-formidable/node-formidable/issues/415)

* feat: introduce Plugins API, fix silent failing tests ([#545](https://github.com/node-formidable/node-formidable/pull/545), [#391](https://github.com/node-formidable/node-formidable/pull/391), [#407](https://github.com/node-formidable/node-formidable/pull/407), [#386](https://github.com/node-formidable/node-formidable/pull/386), [#374](https://github.com/node-formidable/node-formidable/pull/374), [#521](https://github.com/node-formidable/node-formidable/pull/521), [#267](https://github.com/node-formidable/node-formidable/pull/267))
* respect form hash option on incoming octect/stream requests ([#407](https://github.com/node-formidable/node-formidable/pull/407))
* fix: exposing file writable stream errors ([#520](https://github.com/node-formidable/node-formidable/pull/520), [#316](https://github.com/node-formidable/node-formidable/pull/316), [#469](https://github.com/node-formidable/node-formidable/pull/469), [#470](https://github.com/node-formidable/node-formidable/pull/470))
* feat: custom file (re)naming, thru options.filename ([#591](https://github.com/node-formidable/node-formidable/pull/591), [#84](https://github.com/node-formidable/node-formidable/issues/84), [#86](https://github.com/node-formidable/node-formidable/issues/86), [#94](https://github.com/node-formidable/node-formidable/issues/94), [#154](https://github.com/node-formidable/node-formidable/issues/154), [#158](https://github.com/node-formidable/node-formidable/issues/158), [#488](https://github.com/node-formidable/node-formidable/issues/488), [#595](https://github.com/node-formidable/node-formidable/issues/595))
### v1.2.1 (2018-03-20)

@@ -83,1 +90,5 @@

* Fix file handle leak on error (OrangeDog)
---
[First commit, #3270eb4b1f8b (May 4th, 2010)](https://github.com/node-formidable/formidable/commit/3270eb4b1f8bb667b8c12f64c36a4e7b854216d8)
{
"name": "formidable",
"version": "2.0.0-dev.20200131.2",
"version": "2.0.0",
"license": "MIT",
"description": "A node.js module for parsing form data, especially file uploads.",
"homepage": "https://github.com/node-formidable/node-formidable",
"homepage": "https://github.com/node-formidable/formidable",
"funding": "https://ko-fi.com/tunnckoCore/commissions",
"repository": "node-formidable/node-formidable",
"repository": "node-formidable/formidable",
"main": "./src/index.js",
"files": [
"src",
"test"
"CHANGELOG.md",
"LICENSE",
"README.md",
"VERSION_NOTES.md"
],
"publishConfig": {
"access": "public",
"tag": "dev"
"tag": "latest"
},

@@ -24,37 +27,46 @@ "scripts": {

"lint:prepare": "eslint --cache --fix --quiet --format codeframe",
"reinstall": "rm -rf node_modules yarn.lock && yarn",
"pretest": "rm -rf test/tmp && mkdir test/tmp",
"test": "node test/run.js",
"pretest:ci": "yarn pretest",
"test:ci": "nyc node test/run.js"
"reinstall": "del-cli ./node_modules ./yarn.lock",
"postreinstall": "yarn setup",
"setup": "yarn",
"pretest": "del-cli ./test/tmp && make-dir ./test/tmp",
"test": "jest --coverage",
"pretest:ci": "yarn run pretest",
"test:ci": "nyc jest --coverage",
"test:jest": "jest --coverage"
},
"dependencies": {
"dezalgo": "^1.0.3",
"once": "^1.4.0"
"dezalgo": "1.0.3",
"hexoid": "1.0.0",
"once": "1.4.0",
"qs": "6.9.3"
},
"devDependencies": {
"@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4",
"@tunnckocore/prettier-config": "^1.2.0",
"eslint": "^6.8.0",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-prettier": "^3.1.2",
"husky": "^4.2.1",
"jest": "^25.1.0",
"koa": "^2.11.0",
"lint-staged": "^10.0.6",
"nyc": "^15.0.0",
"prettier": "^1.19.1",
"prettier-plugin-pkgjson": "^0.2.0",
"request": "^2.88.0",
"supertest": "^4.0.2",
"urun": "^0.0.8",
"utest": "^0.0.8"
"@commitlint/cli": "8.3.5",
"@commitlint/config-conventional": "8.3.4",
"@tunnckocore/prettier-config": "1.3.8",
"del-cli": "3.0.0",
"eslint": "6.8.0",
"eslint-config-airbnb-base": "14.1.0",
"eslint-config-prettier": "6.11.0",
"eslint-plugin-import": "2.20.2",
"eslint-plugin-prettier": "3.1.3",
"express": "4.17.1",
"husky": "4.2.5",
"jest": "25.4.0",
"koa": "2.11.0",
"lint-staged": "10.2.7",
"make-dir-cli": "2.0.0",
"nyc": "15.0.1",
"prettier": "2.0.5",
"prettier-plugin-pkgjson": "0.2.8",
"request": "2.88.2",
"supertest": "4.0.2"
},
"jest": {
"verbose": true
},
"husky": {
"hooks": {
"pre-commit": "git status --porcelain && lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
"pre-commit": "git status --porcelain && yarn lint-staged",
"commit-msg": "yarn commitlint -E HUSKY_GIT_PARAMS"
}

@@ -74,3 +86,19 @@ },

]
}
},
"renovate": {
"extends": [
"@tunnckocore",
":pinAllExceptPeerDependencies"
]
},
"keywords": [
"multipart",
"form",
"data",
"querystring",
"www",
"json",
"ulpoad",
"file"
]
}
<p align="center">
<img alt="node formidable logo" src="./logo.png" />
<img alt="npm formidable package logo" src="https://raw.githubusercontent.com/node-formidable/formidable/master/logo.png" />
</p>
# formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url]
# formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url] [![Twitter][twitter-img]][twitter-url]

@@ -10,10 +10,38 @@ > A Node.js module for parsing form data, especially file uploads.

[![Code style][codestyle-img]][codestyle-url]
[![build status][build-img]][build-url]
[![codecoverage][codecov-img]][codecov-url]
[![linux build status][linux-build-img]][build-url]
[![windows build status][windows-build-img]][build-url]
[![macos build status][macos-build-img]][build-url]
If you have any _how-to_ kind of questions, please read the [Contributing
Guide][contributing-url] and [Code of Conduct][code_of_conduct-url]
documents.<br /> For bugs reports and feature requests, [please create an
issue][open-issue-url] or ping [@tunnckoCore / @3a1FcBx0](https://twitter.com/3a1FcBx0)
at Twitter.
[![Conventional Commits][ccommits-img]][ccommits-url]
[![Minimum Required Nodejs][nodejs-img]][npmv-url]
[![Tidelift Subcsription][tidelift-img]][tidelift-url]
[![Buy me a Kofi][kofi-img]][kofi-url]
[![Renovate App Status][renovateapp-img]][renovateapp-url]
[![Make A Pull Request][prs-welcome-img]][prs-welcome-url]
[![Twitter][twitter-img]][twitter-url]
## Status: Maintained [![npm version][npmv-canary-img]][npmv-url] [![npm version][npmv-dev-img]][npmv-url]
This project is [semantically versioned](https://semver.org) and available as
part of the [Tidelift Subscription][tidelift-url] for professional grade
assurances, enhanced support and security.
[Learn more.](https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise)
_The maintainers of `formidable` and thousands of other packages are working
with Tidelift to deliver commercial support and maintenance for the Open Source
dependencies you use to build your applications. Save time, reduce risk, and
improve code health, while paying the maintainers of the exact dependencies you
use._
[![][npm-weekly-img]][npmv-url] [![][npm-monthly-img]][npmv-url]
[![][npm-yearly-img]][npmv-url] [![][npm-alltime-img]][npmv-url]
## Project Status: Maintained
_Check [VERSION NOTES](https://github.com/node-formidable/formidable/blob/master/VERSION_NOTES.md) for more information on v1, v2, and v3 plans, NPM dist-tags and branches._
This module was initially developed by

@@ -28,21 +56,12 @@ [**@felixge**](https://github.com/felixge) for

are always welcome! :heart: Jump on
[issue #412](https://github.com/felixge/node-formidable/issues/412) if you are
interested.
[issue #412](https://github.com/felixge/node-formidable/issues/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.
_**Note:** Master is a "canary" branch - try it with `npm i formidable@canary`.
Do not expect (for now) things from it to be inside the`latest`"dist-tag" in the
Npm. The`formidable@latest`is the`v1.2.1` version and probably it will be the
last`v1` release!_
_**Note: v2 is coming soon!**_
You can try the
[Plugins API](https://github.com/felixge/node-formidable/tree/plugins-api)
([#545](https://github.com/felixge/node-formidable/pull/545)), which is
available through `formidable@dev`.
## Highlights
- Fast (~900-2500 mb/sec), streaming multipart parser
- Automatically writing file uploads to disk
- [Fast (~900-2500 mb/sec)](#benchmarks) & streaming multipart parser
- Automatically writing file uploads to disk (optional, see
[`options.fileWriteStreamHandler`](#options))
- [Plugins API](#useplugin-plugin) - allowing custom parsers and plugins
- Low memory footprint

@@ -54,65 +73,182 @@ - Graceful error handling

This project requires `Node.js >= 10.13`. Install it using
[yarn](https://yarnpkg.com) or [npm](https://npmjs.com).<br /> _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/](https://github.com/node-formidable/formidable/tree/master/examples) folder.
```sh
# v2
npm install formidable
# or the canary version
npm install formidable@canary
npm install formidable@latest
npm install formidable@v2
# or v3
npm install formidable@v3
```
or with Yarn v1/v2
_**Note:** In near future v3 will be published on the `latest` NPM dist-tag. Future not ready releases will continue to be published on `canary` dist-tag._
```sh
yarn add formidable
# or the canary version
yarn add formidable@canary
```
This is a low-level package, and if you're using a high-level framework it may
already be included.
## Examples
However, [Express v4](http://expressjs.com) does not include any multipart
handling, nor does [body-parser](https://github.com/expressjs/body-parser).
For more examples look at the `examples/` directory.
For `koa` there is [koa-better-body](https://ghub.now.sh/koa-better-body) which
can handle ANY type of body / form-data - JSON, urlencoded, multpart and so on.
A new major release is coming there too.
### with Node.js http module
## Example
Parse an incoming file upload, with the
[Node.js's built-in `http` module](https://nodejs.org/api/http.html).
Parse an incoming file upload.
```js
const http = require('http');
const util = require('util');
const formidable = require('formidable');
http
.createServer((req, res) => {
if (req.url === '/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable();
const server = http.createServer((req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
res.writeHead(200, { 'content-type': 'text/plain' });
res.write('received upload:\n\n');
res.end(util.inspect({ fields: fields, files: files }));
});
form.parse(req, (err, fields, files) => {
if (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/ ...');
});
```
### with Express.js
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](https://ghub.now.sh/express) middleware.
Or try the
[examples/with-express.js](https://github.com/node-formidable/formidable/blob/master/examples/with-express.js)
```js
const express = require('express');
const formidable = require('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({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
// show a file upload form
res.writeHead(200, { 'content-type': 'text/html' });
res.end(`
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="text" name="title" /><br/>
<input type="file" name="upload" multiple="multiple" /><br/>
<input type="submit" value="Upload" />
</form>
`);
})
.listen(8080, () => {
console.log('Server listening on http://localhost:8080/ ...');
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
```
### with Koa and Formidable
Of course, with [Koa v1, v2 or future v3](https://ghub.now.sh/koa) the things
are very similar. You can use `formidable` manually as shown below or through
the [koa-better-body](https://ghub.now.sh/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._
```js
const Koa = require('koa');
const formidable = require('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({ multiples: true });
// 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 ...');
});
```
## Benchmarks

@@ -158,4 +294,4 @@

_Please pass [`options`](#options) to the function/constructor, not by passing
assigning them to the instance `form`_
_Please pass [`options`](#options) to the function/constructor, not by assigning
them to the instance `form`_

@@ -181,4 +317,4 @@ ```js

See it's defaults in [src/Formidable.js](./src/Formidable.js#L14-L22) (the
`DEFAULT_OPTIONS` constant).
See it's defaults in [src/Formidable.js DEFAULT_OPTIONS](./src/Formidable.js)
(the `DEFAULT_OPTIONS` constant).

@@ -188,16 +324,29 @@ - `options.encoding` **{string}** - default `'utf-8'`; sets encoding for

- `options.uploadDir` **{string}** - default `os.tmpdir()`; the directory for
placing file uploads in. You can move them later by using `fs.rename()`
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 `true`; allow upload empty
files
- `options.minFileSize` **{number}** - default `1` (1byte); the minium size of
uploaded file.
- `options.maxFileSize` **{number}** - default `200 * 1024 * 1024` (200mb);
limit the size of uploaded file.
- `options.maxFields` **{number}** - default `1000`; limit the number of fields
that the Querystring parser will decode, set 0 for unlimited
- `options.maxFields` **{number}** - default `1000`; limit the number of fields, set 0 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.hash` **{boolean}** - default `false`; include checksums calculated
- `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.multiples` **{boolean}** - default `false`; when you call the

@@ -208,5 +357,14 @@ `.parse` method, the `files` argument (of the callback) will contain arrays of

fields that have names ending with '[]'.
- `options.filename` **{function}** - default `undefined` Use it to control
newFilename. Must return a string. Will be joined with options.uploadDir.
_**Note:** If this value is exceeded, an `'error'` event is emitted._
- `options.filter` **{function}** - default function that always returns true.
Use it to filter files before they are uploaded. Must return a boolean.
#### `options.filename` **{function}** function (name, ext, part, form) -> string
_**Note:** If this size of combined fields, or size of some file is exceeded, an
`'error'` event is fired._
```js

@@ -222,2 +380,16 @@ // The amount of bytes received for this form so far.

#### `options.filter` **{function}** function ({name, originalFilename, mimetype}) -> boolean
**Note:** use an outside variable to cancel all uploads upon the first error
```js
const options = {
filter: function ({name, originalFilename, mimetype}) {
// keep only images
return mimetype && mimetype.includes("image");
}
};
```
### .parse(request, callback)

@@ -244,2 +416,37 @@

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)
```js
`${__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:
```js
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

@@ -256,8 +463,8 @@ `data` listener, so you can do whatever you choose there, based on whether its

form.on('fileBegin', (filename, file) => {
form.emit('data', { name: 'fileBegin', filename, value: file });
form.on('fileBegin', (formname, file) => {
form.emit('data', { name: 'fileBegin', formname, value: file });
});
form.on('file', (filename, file) => {
form.emit('data', { name: 'file', key: filename, value: file });
form.on('file', (formname, file) => {
form.emit('data', { name: 'file', formname, value: file });
});

@@ -274,3 +481,3 @@

// If you want to customize whatever you want...
form.on('data', ({ name, key, value, buffer, start, end, ...more }) => {
form.on('data', ({ name, key, value, buffer, start, end, formname, ...more }) => {
if (name === 'partBegin') {

@@ -293,6 +500,6 @@ }

if (name === 'file') {
console.log('file:', key, value);
console.log('file:', formname, value);
}
if (name === 'fileBegin') {
console.log('fileBegin:', key, value);
console.log('fileBegin:', formname, value);
}

@@ -352,3 +559,3 @@ });

const form = new Formidable({
hash: 'sha1',
hashAlgorithm: 'sha1',
enabledPlugins: ['octetstream', 'querystring', 'json'],

@@ -376,3 +583,3 @@ });

form.onPart = (part) => {
part.on('data', (buffer) {
part.on('data', (buffer) => {
// do whatever you want here

@@ -389,7 +596,7 @@ });

form.onPart = function(part) {
form.onPart = function (part) {
// let formidable handle only non-file parts
if (part.filename === '' || !part.mime) {
if (part.originalFilename === '' || !part.mimetype) {
// used internally, please do not override!
form.handlePart(part);
form._handlePart(part);
}

@@ -410,16 +617,20 @@ };

// case you are unhappy with the way formidable generates a temporary path for your files.
file.path: string;
file.filepath: string;
// The name this file had according to the uploading client.
file.name: string | null;
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.type: string | null;
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.lastModifiedDate: Date | null;
file.mtime: Date | null;
// If `options.hash` calculation was set, you can read the hex digest out of this var.
file.hash: string | 'sha1' | 'md5' | 'sha256' | 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;
}

@@ -460,3 +671,10 @@ ```

```js
form.on('fileBegin', (name, file) => {});
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 pathnme as per options.uploadDir and options.filename
// file.filepath = CUSTOM_PATH // to change the final path
});
```

@@ -470,3 +688,7 @@

```js
form.on('file', (name, 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
});
```

@@ -480,2 +702,4 @@

May have `error.httpCode` and `error.code` attached.
```js

@@ -505,2 +729,6 @@ form.on('error', (err) => {});

## Changelog
[./CHANGELOG.md](./CHANGELOG.md)
## Ports & Credits

@@ -518,4 +746,4 @@

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](./CONTRIBUTING.md). Pull requests are welcome!
a bug or add a new feature, please check our [Contributing
Guide][contributing-url]. Pull requests are welcome!

@@ -550,2 +778,3 @@ Thanks goes to these wonderful people

<td align="center"><a href="https://github.com/dmolim"><img src="https://avatars2.githubusercontent.com/u/7090374?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Ivonin</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=dmolim" title="Documentation">📖</a></td>
<td align="center"><a href="https://audiobox.fm"><img src="https://avatars1.githubusercontent.com/u/12844?v=4" width="100px;" alt=""/><br /><sub><b>Claudio Poli</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=masterkain" title="Code">💻</a></td>
</tr>

@@ -559,2 +788,9 @@ </table>

From a [Felix blog post](https://felixge.de/2013/03/11/the-pull-request-hack/):
- [Sven Lito](https://github.com/svnlto) for fixing bugs and merging patches
- [egirshov](https://github.com/egirshov) for contributing many improvements to the node-formidable multipart parser
- [Andrew Kelley](https://github.com/superjoe30) for also helping with fixing bugs and making improvements
- [Mike Frey](https://github.com/mikefrey) for contributing JSON support
## License

@@ -569,6 +805,4 @@

[codestyle-img]: https://badgen.net/badge/code%20style/airbnb%20%2B%20prettier/ff5a5f?icon=airbnb&cache=300
[codecov-url]: https://codecov.io/gh/node-formidable/node-formidable
[codecov-img]: https://badgen.net/codecov/c/github/node-formidable/node-formidable/master?icon=codecov
[build-img]: https://badgen.net/github/checks/node-formidable/node-formidable?label=build&icon=github
[build-url]: https://github.com/node-formidable/node-formidable/actions?query=workflow%3Anodejs
[codecov-url]: https://codecov.io/gh/node-formidable/formidable
[codecov-img]: https://badgen.net/codecov/c/github/node-formidable/formidable/master?icon=codecov
[npmv-canary-img]: https://badgen.net/npm/v/formidable/canary?icon=npm

@@ -579,3 +813,3 @@ [npmv-dev-img]: https://badgen.net/npm/v/formidable/dev?icon=npm

[license-img]: https://badgen.net/npm/license/formidable
[license-url]: https://github.com/node-formidable/node-formidable/blob/master/LICENSE
[license-url]: https://github.com/node-formidable/formidable/blob/master/LICENSE
[chat-img]: https://badgen.net/badge/chat/on%20gitter/46BC99?icon=gitter

@@ -589,5 +823,30 @@ [chat-url]: https://gitter.im/node-formidable/Lobby

[prs-welcome-url]: http://makeapullrequest.com
[twitter-url]: https://twitter.com/tunnckoCore
[twitter-img]: https://badgen.net/twitter/follow/tunnckoCore?icon=twitter&color=1da1f2&cache=300
[twitter-url]: https://twitter.com/3a1fcBx0
[twitter-img]: https://badgen.net/twitter/follow/3a1fcBx0?icon=twitter&color=1da1f2&cache=300
[npm-weekly-img]: https://badgen.net/npm/dw/formidable?icon=npm&cache=300
[npm-monthly-img]: https://badgen.net/npm/dm/formidable?icon=npm&cache=300
[npm-yearly-img]: https://badgen.net/npm/dy/formidable?icon=npm&cache=300
[npm-alltime-img]: https://badgen.net/npm/dt/formidable?icon=npm&cache=300&label=total%20downloads
[nodejs-img]: https://badgen.net/badge/node/>=%2010.13/green?cache=300
[ccommits-url]: https://conventionalcommits.org/
[ccommits-img]: https://badgen.net/badge/conventional%20commits/v1.0.0/green?cache=300
[contributing-url]: https://github.com/node-formidable/.github/blob/master/CONTRIBUTING.md
[code_of_conduct-url]: https://github.com/node-formidable/.github/blob/master/CODE_OF_CONDUCT.md
[open-issue-url]: https://github.com/node-formidable/formidable/issues/new
[tidelift-url]: https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise
[tidelift-img]: https://badgen.net/badge/tidelift/subscription/4B5168?labelColor=F6914D
[kofi-url]: https://ko-fi.com/tunnckoCore/commissions
[kofi-img]: https://badgen.net/badge/ko-fi/support/29abe0c2?cache=300&icon=https://rawcdn.githack.com/tunnckoCore/badgen-icons/f8264c6414e0bec449dd86f2241d50a9b89a1203/icons/kofi.svg
[linux-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master/ubuntu?cache=300&label=linux%20build&icon=github
[macos-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master/macos?cache=300&label=macos%20build&icon=github
[windows-build-img]: https://badgen.net/github/checks/node-formidable/formidable/master/windows?cache=300&label=windows%20build&icon=github
[build-url]: https://github.com/node-formidable/formidable/actions?query=workflow%3Anodejs
<!-- prettier-ignore-end -->

@@ -7,5 +7,4 @@ /* eslint-disable class-methods-use-this */

const os = require('os');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const hexoid = require('hexoid');
const once = require('once');

@@ -15,3 +14,5 @@ const dezalgo = require('dezalgo');

const { StringDecoder } = require('string_decoder');
const qs = require('qs');
const toHexoId = hexoid(25);
const DEFAULT_OPTIONS = {

@@ -21,13 +22,25 @@ maxFields: 1000,

maxFileSize: 200 * 1024 * 1024,
minFileSize: 1,
allowEmptyFiles: true,
keepExtensions: false,
encoding: 'utf-8',
hash: false,
hashAlgorithm: false,
uploadDir: os.tmpdir(),
multiples: false,
enabledPlugins: ['octetstream', 'querystring', 'multipart', 'json'],
fileWriteStreamHandler: null,
defaultInvalidName: 'invalid-name',
filter: function () {
return true;
},
};
const File = require('./File');
const PersistentFile = require('./PersistentFile');
const VolatileFile = require('./VolatileFile');
const DummyParser = require('./parsers/Dummy');
const MultipartParser = require('./parsers/Multipart');
const errors = require('./FormidableError.js');
const { FormidableError } = errors;
function hasOwnProp(obj, key) {

@@ -40,15 +53,26 @@ return Object.prototype.hasOwnProperty.call(obj, key);

super();
this.error = null;
this.ended = false;
this.options = { ...DEFAULT_OPTIONS, ...options };
this.uploadDir = this.uploadDir || os.tmpdir();
this.headers = null;
this.type = null;
const dir = path.resolve(
this.options.uploadDir || this.options.uploaddir || os.tmpdir(),
);
this.bytesReceived = null;
this.bytesExpected = null;
this.uploaddir = dir;
this.uploadDir = dir;
this._parser = null;
// initialize with null
[
'error',
'headers',
'type',
'bytesExpected',
'bytesReceived',
'_parser',
].forEach((key) => {
this[key] = null;
});
this._setUpRename();
this._flushing = 0;

@@ -60,9 +84,10 @@ this._fieldsSize = 0;

const enabledPlugins = []
this.options.enabledPlugins = []
.concat(this.options.enabledPlugins)
.filter(Boolean);
if (enabledPlugins.length === 0) {
throw new Error(
if (this.options.enabledPlugins.length === 0) {
throw new FormidableError(
'expect at least 1 enabled builtin plugin, see options.enabledPlugins',
errors.missingPlugin,
);

@@ -76,2 +101,4 @@ }

});
this._setUpMaxFields();
}

@@ -81,3 +108,6 @@

if (typeof plugin !== 'function') {
throw new Error('.use: expect `plugin` to be a function');
throw new FormidableError(
'.use: expect `plugin` to be a function',
errors.pluginFunction,
);
}

@@ -122,23 +152,17 @@ this._plugins.push(plugin.bind(this));

const fields = {};
let mockFields = '';
const files = {};
this.on('field', (name, value) => {
// TODO: too much nesting
if (this.options.multiples && name.slice(-2) === '[]') {
const realName = name.slice(0, name.length - 2);
if (hasOwnProp(fields, realName)) {
if (!Array.isArray(fields[realName])) {
fields[realName] = [fields[realName]];
}
} else {
fields[realName] = [];
}
fields[realName].push(value);
if (
this.options.multiples &&
(this.type === 'multipart' || this.type === 'urlencoded')
) {
const mObj = { [name]: value };
mockFields = mockFields
? `${mockFields}&${qs.stringify(mObj)}`
: `${qs.stringify(mObj)}`;
} else {
fields[name] = value;
}
// if (name === 'simple') {
// console.log('fields name!!', name);
// console.log('fields value!!', value);
// }
});

@@ -159,7 +183,2 @@ this.on('file', (name, file) => {

}
// console.log('files!!', files);
// if (name === 'simple') {
// console.log('files name!!', name);
// console.log('files value!!', file);
// }
});

@@ -170,2 +189,5 @@ this.on('error', (err) => {

this.on('end', () => {
if (this.options.multiples) {
Object.assign(fields, qs.parse(mockFields));
}
callback(null, fields, files);

@@ -185,3 +207,3 @@ });

this.emit('aborted');
this._error(new Error('Request aborted'));
this._error(new FormidableError('Request aborted', errors.aborted));
})

@@ -214,3 +236,9 @@ .on('data', (buffer) => {

if (!this._parser) {
this._error(new Error('not parser found'));
this._error(
new FormidableError(
'no parser found',
errors.noParser,
415, // Unsupported Media Type
),
);
return;

@@ -229,3 +257,5 @@ }

if (!this._parser) {
this._error(new Error('uninitialized parser'));
this._error(
new FormidableError('uninitialized parser', errors.uninitializedParser),
);
return null;

@@ -258,8 +288,13 @@ }

_handlePart(part) {
if (part.filename && typeof part.filename !== 'string') {
this._error(new Error(`the part.filename should be string when exists`));
if (part.originalFilename && typeof part.originalFilename !== 'string') {
this._error(
new FormidableError(
`the part.originalFilename should be string when it exists`,
errors.filenameNotString,
),
);
return;
}
// This MUST check exactly for undefined. You can not change it to !part.filename.
// This MUST check exactly for undefined. You can not change it to !part.originalFilename.

@@ -272,5 +307,5 @@ // todo: uncomment when switch tests to Jest

// and such thing because code style
// ? NOTE(@tunnckocore): or even better, if there is no mime, then it's for sure a field
// ? NOTE(@tunnckocore): filename is an empty string when a field?
if (!part.mime) {
// ? NOTE(@tunnckocore): or even better, if there is no mimetype, then it's for sure a field
// ? NOTE(@tunnckocore): originalFilename is an empty string when a field?
if (!part.mimetype) {
let value = '';

@@ -285,4 +320,6 @@ const decoder = new StringDecoder(

this._error(
new Error(
`options.maxFieldsSize exceeded, received ${this._fieldsSize} bytes of field data`,
new FormidableError(
`options.maxFieldsSize (${this.options.maxFieldsSize} bytes) exceeded, received ${this._fieldsSize} bytes of field data`,
errors.maxFieldsSizeExceeded,
413, // Payload Too Large
),

@@ -301,9 +338,15 @@ );

if (!this.options.filter(part)) {
return;
}
this._flushing += 1;
const file = new File({
path: this._uploadPath(part.filename),
name: part.filename,
type: part.mime,
hash: this.options.hash,
const newFilename = this._getNewName(part);
const filepath = this._joinDirectoryName(newFilename);
const file = this._newFile({
newFilename,
filepath,
originalFilename: part.originalFilename,
mimetype: part.mimetype,
});

@@ -320,6 +363,18 @@ file.on('error', (err) => {

this._fileSize += buffer.length;
if (this._fileSize < this.options.minFileSize) {
this._error(
new FormidableError(
`options.minFileSize (${this.options.minFileSize} bytes) inferior, received ${this._fileSize} bytes of file data`,
errors.smallerThanMinFileSize,
400,
),
);
return;
}
if (this._fileSize > this.options.maxFileSize) {
this._error(
new Error(
`options.maxFileSize exceeded, received ${this._fileSize} bytes of file data`,
new FormidableError(
`options.maxFileSize (${this.options.maxFileSize} bytes) exceeded, received ${this._fileSize} bytes of file data`,
errors.biggerThanMaxFileSize,
413,
),

@@ -339,2 +394,13 @@ );

part.on('end', () => {
if (!this.options.allowEmptyFiles && this._fileSize === 0) {
this._error(
new FormidableError(
`options.allowEmptyFiles is false, file size should be greather than 0`,
errors.noEmptyFiles,
400,
),
);
return;
}
file.end(() => {

@@ -356,3 +422,9 @@ this._flushing -= 1;

if (!this.headers['content-type']) {
this._error(new Error('bad content-type header, no content-type'));
this._error(
new FormidableError(
'bad content-type header, no content-type',
errors.missingContentType,
400,
),
);
return;

@@ -375,4 +447,6 @@ }

// there is no other better way, except a handle through options
const error = new Error(
const error = new FormidableError(
`plugin on index ${idx} failed with: ${err.message}`,
errors.pluginFailed,
500,
);

@@ -416,4 +490,3 @@ error.idx = idx;

this.openedFiles.forEach((file) => {
file._writeStream.destroy();
setTimeout(fs.unlink, 0, file.path, () => {});
file.destroy();
});

@@ -440,7 +513,25 @@ }

_newFile({ filepath, originalFilename, mimetype, newFilename }) {
return this.options.fileWriteStreamHandler
? new VolatileFile({
newFilename,
filepath,
originalFilename,
mimetype,
createFileWriteStream: this.options.fileWriteStreamHandler,
hashAlgorithm: this.options.hashAlgorithm,
})
: new PersistentFile({
newFilename,
filepath,
originalFilename,
mimetype,
hashAlgorithm: this.options.hashAlgorithm,
});
}
_getFileName(headerValue) {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(
// eslint-disable-next-line no-useless-escape
/\bfilename=("(.*?)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))($|;\s)/i,
/\bfilename=("(.*?)"|([^()<>{}[\]@,;:"?=\s/\t]+))($|;\s)/i,
);

@@ -450,24 +541,88 @@ if (!m) return null;

const match = m[2] || m[3] || '';
let filename = match.substr(match.lastIndexOf('\\') + 1);
filename = filename.replace(/%22/g, '"');
filename = filename.replace(/&#([\d]{4});/g, (_, code) =>
let originalFilename = match.substr(match.lastIndexOf('\\') + 1);
originalFilename = originalFilename.replace(/%22/g, '"');
originalFilename = originalFilename.replace(/&#([\d]{4});/g, (_, code) =>
String.fromCharCode(code),
);
return filename;
return originalFilename;
}
_uploadPath(filename) {
const buf = crypto.randomBytes(16);
let name = `upload_${buf.toString('hex')}`;
_getExtension(str) {
if (!str) {
return '';
}
if (this.options.keepExtensions) {
let ext = path.extname(filename);
ext = ext.replace(/(\.[a-z0-9]+).*/i, '$1');
const basename = path.basename(str);
const firstDot = basename.indexOf('.');
const lastDot = basename.lastIndexOf('.');
const extname = path.extname(basename).replace(/(\.[a-z0-9]+).*/i, '$1');
name += ext;
if (firstDot === lastDot) {
return extname;
}
return path.join(this.uploadDir, name);
return basename.slice(firstDot, lastDot) + extname;
}
_joinDirectoryName(name) {
const newPath = path.join(this.uploadDir, name);
// prevent directory traversal attacks
if (!newPath.startsWith(this.uploadDir)) {
return path.join(this.uploadDir, this.options.defaultInvalidName);
}
return newPath;
}
_setUpRename() {
const hasRename = typeof this.options.filename === 'function';
if (hasRename) {
this._getNewName = (part) => {
let ext = '';
let name = this.options.defaultInvalidName;
if (part.originalFilename) {
// can be null
({ ext, name } = path.parse(part.originalFilename));
if (this.options.keepExtensions !== true) {
ext = '';
}
}
return this.options.filename.call(this, name, ext, part, this);
};
} else {
this._getNewName = (part) => {
const name = toHexoId();
if (part && this.options.keepExtensions) {
const originalFilename = typeof part === 'string' ? part : part.originalFilename;
return `${name}${this._getExtension(originalFilename)}`;
}
return name;
}
}
}
_setUpMaxFields() {
if (this.options.maxFields !== 0) {
let fieldsCount = 0;
this.on('field', () => {
fieldsCount += 1;
if (fieldsCount > this.options.maxFields) {
this._error(
new FormidableError(
`options.maxFields (${this.options.maxFields}) exceeded`,
errors.maxFieldsExceeded,
413,
),
);
}
});
}
}
_maybeEnd() {

@@ -474,0 +629,0 @@ // console.log('ended', this.ended);

'use strict';
const File = require('./File');
const PersistentFile = require('./PersistentFile');
const VolatileFile = require('./VolatileFile');
const Formidable = require('./Formidable');
const FormidableError = require('./FormidableError');

@@ -14,3 +16,6 @@ const plugins = require('./plugins/index');

module.exports = Object.assign(formidable, {
File,
errors: FormidableError,
File: PersistentFile,
PersistentFile,
VolatileFile,
Formidable,

@@ -17,0 +22,0 @@ formidable,

@@ -0,0 +0,0 @@ /* eslint-disable no-underscore-dangle */

@@ -0,0 +0,0 @@ 'use strict';

@@ -0,0 +0,0 @@ /* eslint-disable no-underscore-dangle */

@@ -9,3 +9,6 @@ /* eslint-disable no-fallthrough */

const { Transform } = require('stream');
const errors = require('../FormidableError.js');
const { FormidableError } = errors;
let s = 0;

@@ -63,3 +66,3 @@ const STATE = {

_final(done) {
_flush(done) {
if (

@@ -74,4 +77,6 @@ (this.state === STATE.HEADER_FIELD_START && this.index === 0) ||

done(
new Error(
new FormidableError(
`MultipartParser.end(): stream ended unexpectedly: ${this.explain()}`,
errors.malformedMultipart,
400,
),

@@ -114,3 +119,3 @@ );

const setMark = (name, idx) => {
this[`${name}Mark`] = idx || i;
this[`${name}Mark`] = typeof idx === 'number' ? idx : i;
};

@@ -130,6 +135,6 @@

this._handleCallback(name, buffer, this[markSymbol], buffer.length);
setMark(markSymbol, 0);
setMark(name, 0);
} else {
this._handleCallback(name, buffer, this[markSymbol], i);
clearMarkSymbol(markSymbol);
clearMarkSymbol(name);
}

@@ -136,0 +141,0 @@ };

@@ -0,0 +0,0 @@ 'use strict';

@@ -14,3 +14,2 @@ /* eslint-disable no-underscore-dangle */

this.globalOptions = { ...options };
this.maxKeys = this.globalOptions.maxFields;
this.buffer = '';

@@ -27,5 +26,3 @@ this.bufferLength = 0;

_flush(callback) {
const fields = querystring.parse(this.buffer, '&', '=', {
maxKeys: this.maxKeys,
});
const fields = querystring.parse(this.buffer, '&', '=');
// eslint-disable-next-line no-restricted-syntax, guard-for-in

@@ -32,0 +29,0 @@ for (const key in fields) {

@@ -0,0 +0,0 @@ 'use strict';

@@ -0,0 +0,0 @@ /* eslint-disable no-underscore-dangle */

@@ -7,3 +7,6 @@ /* eslint-disable no-underscore-dangle */

const MultipartParser = require('../parsers/Multipart');
const errors = require('../FormidableError.js');
const { FormidableError } = errors;
// the `options` is also available through the `options` / `formidable.options`

@@ -17,3 +20,6 @@ module.exports = function plugin(formidable, options) {

if (/multipart\/form-data/i.test(self.headers['content-type'])) {
// NOTE: we (currently) support both multipart/form-data and multipart/related
const multipart = /multipart/i.test(self.headers['content-type']);
if (multipart) {
const m = self.headers['content-type'].match(

@@ -24,5 +30,9 @@ /boundary=(?:"([^"]+)"|([^;]+))/i,

const initMultipart = createInitMultipart(m[1] || m[2]);
initMultipart.call(self, self, options);
initMultipart.call(self, self, options); // lgtm [js/superfluous-trailing-arguments]
} else {
const err = new Error('bad content-type header, no multipart boundary');
const err = new FormidableError(
'bad content-type header, no multipart boundary',
errors.missingMultipartBoundary,
400,
);
self._error(err);

@@ -54,6 +64,6 @@ }

part.name = null;
part.filename = null;
part.mime = null;
part.originalFilename = null;
part.mimetype = null;
part.transferEncoding = 'binary';
part.transferEncoding = this.options.encoding;
part.transferBuffer = '';

@@ -81,5 +91,5 @@

part.filename = this._getFileName(headerValue);
part.originalFilename = this._getFileName(headerValue);
} else if (headerField === 'content-type') {
part.mime = headerValue;
part.mimetype = headerValue;
} else if (headerField === 'content-transfer-encoding') {

@@ -95,3 +105,4 @@ part.transferEncoding = headerValue.toLowerCase();

case '7bit':
case '8bit': {
case '8bit':
case 'utf-8': {
const dataPropagation = (ctx) => {

@@ -150,3 +161,9 @@ if (ctx.name === 'partData') {

default:
return this._error(new Error('unknown transfer-encoding'));
return this._error(
new FormidableError(
'unknown transfer-encoding',
errors.unknownTransferEncoding,
501,
),
);
}

@@ -153,0 +170,0 @@

@@ -5,3 +5,2 @@ /* eslint-disable no-underscore-dangle */

const File = require('../File');
const OctetStreamParser = require('../parsers/OctetStream');

@@ -29,13 +28,19 @@

this.type = 'octet-stream';
const filename = this.headers['x-file-name'];
const mime = this.headers['content-type'];
const originalFilename = this.headers['x-file-name'];
const mimetype = this.headers['content-type'];
const file = new File({
path: this._uploadPath(filename),
name: filename,
type: mime,
hash: this.options.hash,
const thisPart = {
originalFilename,
mimetype,
};
const newFilename = this._getNewName(thisPart);
const filepath = this._joinDirectoryName(newFilename);
const file = this._newFile({
newFilename,
filepath,
originalFilename,
mimetype,
});
this.emit('fileBegin', filename, file);
this.emit('fileBegin', originalFilename, file);
file.open();

@@ -42,0 +47,0 @@ this.openedFiles.push(file);

@@ -0,0 +0,0 @@ /* eslint-disable no-underscore-dangle */

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc