pax_global_header 0000666 0000000 0000000 00000000064 15002044507 0014507 g ustar 00root root 0000000 0000000 52 comment=d0fbec13edc8add54a1afb9ce1a8d3db803f8d47
node-formidable-formidable-63c2d93/ 0000775 0000000 0000000 00000000000 15002044507 0017177 5 ustar 00root root 0000000 0000000 node-formidable-formidable-63c2d93/.all-contributorsrc 0000664 0000000 0000000 00000011644 15002044507 0023036 0 ustar 00root root 0000000 0000000 {
"projectName": "node-formidable",
"projectOwner": "node-formidable",
"repoType": "github",
"repoHost": "https://github.com",
"imageSize": 100,
"contributorsPerLine": 6,
"commitConvention": "angular",
"commit": true,
"skipCi": true,
"files": [
"README.md"
],
"contributors": [
{
"login": "felixge",
"name": "Felix Geisendörfer",
"avatar_url": "https://avatars3.githubusercontent.com/u/15000?s=460&v=4",
"profile": "https://twitter.com/felixge",
"contributions": [
"code",
"design",
"ideas",
"doc"
]
},
{
"login": "tunnckoCore",
"name": "Charlike Mike Reagent",
"avatar_url": "https://avatars3.githubusercontent.com/u/5038030?v=4",
"profile": "https://tunnckoCore.com",
"contributions": [
"bug",
"infra",
"design",
"code",
"doc",
"example",
"ideas",
"maintenance",
"test"
]
},
{
"login": "kedarv",
"name": "Kedar",
"avatar_url": "https://avatars1.githubusercontent.com/u/1365665?v=4",
"profile": "https://github.com/kedarv",
"contributions": [
"code",
"test",
"question",
"bug"
]
},
{
"login": "GrosSacASac",
"name": "Walle Cyril",
"avatar_url": "https://avatars0.githubusercontent.com/u/5721194?v=4",
"profile": "https://github.com/GrosSacASac",
"contributions": [
"question",
"bug",
"code",
"financial",
"ideas",
"maintenance"
]
},
{
"login": "xarguments",
"name": "Xargs",
"avatar_url": "https://avatars2.githubusercontent.com/u/40522463?v=4",
"profile": "https://github.com/xarguments",
"contributions": [
"question",
"bug",
"code",
"maintenance"
]
},
{
"login": "Amit-A",
"name": "Amit-A",
"avatar_url": "https://avatars1.githubusercontent.com/u/7987238?v=4",
"profile": "https://github.com/Amit-A",
"contributions": [
"question",
"bug",
"code"
]
},
{
"login": "charmander",
"name": "Charmander",
"avatar_url": "https://avatars1.githubusercontent.com/u/1889843?v=4",
"profile": "https://charmander.me/",
"contributions": [
"question",
"bug",
"code",
"ideas",
"maintenance"
]
},
{
"login": "DylanPiercey",
"name": "Dylan Piercey",
"avatar_url": "https://avatars2.githubusercontent.com/u/4985201?v=4",
"profile": "https://twitter.com/dylan_piercey",
"contributions": [
"ideas"
]
},
{
"login": "ad-m",
"name": "Adam Dobrawy",
"avatar_url": "https://avatars1.githubusercontent.com/u/3618479?v=4",
"profile": "http://ochrona.jawne.info.pl",
"contributions": [
"bug",
"doc"
]
},
{
"login": "amitrohatgi",
"name": "amitrohatgi",
"avatar_url": "https://avatars3.githubusercontent.com/u/12177021?v=4",
"profile": "https://github.com/amitrohatgi",
"contributions": [
"ideas"
]
},
{
"login": "fengxinming",
"name": "Jesse Feng",
"avatar_url": "https://avatars2.githubusercontent.com/u/6262382?v=4",
"profile": "https://github.com/fengxinming",
"contributions": [
"bug"
]
},
{
"login": "quantumsheep",
"name": "Nathanael Demacon",
"avatar_url": "https://avatars1.githubusercontent.com/u/7271496?v=4",
"profile": "https://qtmsheep.com",
"contributions": [
"question",
"code",
"review"
]
},
{
"login": "MunMunMiao",
"name": "MunMunMiao",
"avatar_url": "https://avatars1.githubusercontent.com/u/18216142?v=4",
"profile": "https://github.com/MunMunMiao",
"contributions": [
"bug"
]
},
{
"login": "gabipetrovay",
"name": "Gabriel Petrovay",
"avatar_url": "https://avatars0.githubusercontent.com/u/1170398?v=4",
"profile": "https://github.com/gabipetrovay",
"contributions": [
"bug",
"code"
]
},
{
"login": "Elzair",
"name": "Philip Woods",
"avatar_url": "https://avatars0.githubusercontent.com/u/2352818?v=4",
"profile": "https://github.com/Elzair",
"contributions": [
"code",
"ideas"
]
},
{
"login": "dmolim",
"name": "Dmitry Ivonin",
"avatar_url": "https://avatars2.githubusercontent.com/u/7090374?v=4",
"profile": "https://github.com/dmolim",
"contributions": [
"doc"
]
},
{
"login": "masterkain",
"name": "Claudio Poli",
"avatar_url": "https://avatars1.githubusercontent.com/u/12844?v=4",
"profile": "https://audiobox.fm",
"contributions": [
"code"
]
}
]
}
node-formidable-formidable-63c2d93/.editorconfig 0000664 0000000 0000000 00000000344 15002044507 0021655 0 ustar 00root root 0000000 0000000 # http://editorconfig.org/
root = true
[*]
indent_style = space
indent_size = 2
tab_width = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = true
node-formidable-formidable-63c2d93/.eslintignore 0000664 0000000 0000000 00000000454 15002044507 0021705 0 ustar 00root root 0000000 0000000 # Ignore everything!
*
# de-ignores: add here what you want to be committed
!*.*js*
!*.ts*
!*.md*
!**/src
!**/src/**
!**/test
!**/test/**
!**/*tests*
!**/*tests*/**
!**/benchmark*
!**/benchmark*/**
!**/example*
!**/example*/**
# re-ignores: add here what you want to be ignored again
test/tmp
node-formidable-formidable-63c2d93/.eslintrc.cjs 0000664 0000000 0000000 00000012171 15002044507 0021603 0 ustar 00root root 0000000 0000000 'use strict';
const airbnbBase = require('eslint-config-airbnb-base');
// eslint-disable-next-line import/no-dynamic-require
const bestPractices = require(airbnbBase.extends[0]);
const ignoredProps = bestPractices.rules[
'no-param-reassign'
][1].ignorePropertyModificationsFor.concat(
'err',
'x',
'_',
'opts',
'options',
'settings',
'config',
'cfg',
);
// Additional rules that are specific and overriding previous
const additionalChanges = {
strict: 'off',
// Enforce using named functions when regular function is used,
// otherwise use arrow functions
'func-names': ['error', 'always'],
// Always use parens (for consistency).
// https://eslint.org/docs/rules/arrow-parens
'arrow-parens': ['error', 'always', { requireForBlockBody: true }],
'prefer-arrow-callback': [
'error',
{ allowNamedFunctions: true, allowUnboundThis: true },
],
// http://eslint.org/docs/rules/max-params
'max-params': ['error', { max: 3 }],
// http://eslint.org/docs/rules/max-statements
'max-statements': ['error', { max: 20 }],
// http://eslint.org/docs/rules/max-statements-per-line
'max-statements-per-line': ['error', { max: 1 }],
// http://eslint.org/docs/rules/max-nested-callbacks
'max-nested-callbacks': ['error', { max: 4 }],
// http://eslint.org/docs/rules/max-depth
'max-depth': ['error', { max: 4 }],
// enforces no braces where they can be omitted
// https://eslint.org/docs/rules/arrow-body-style
// Never enable for object literal.
'arrow-body-style': [
'error',
'as-needed',
{ requireReturnForObjectLiteral: false },
],
// Allow functions to be use before define because:
// 1) they are hoisted,
// 2) because ensure read flow is from top to bottom
// 3) logically order of the code.
// 4) the only addition is 'typedefs' option, see overrides for TS files
'no-use-before-define': [
'error',
{
functions: false,
classes: true,
variables: true,
},
],
// Same as AirBnB, but adds `opts`, `options`, `x` and `err` to exclusions!
// disallow reassignment of function parameters
// disallow parameter object manipulation except for specific exclusions
// rule: https://eslint.org/docs/rules/no-param-reassign.html
'no-param-reassign': [
'error',
{
props: true,
ignorePropertyModificationsFor: ignoredProps,
},
],
// disallow declaration of variables that are not used in the code
'no-unused-vars': [
'error',
{
ignoreRestSiblings: true, // airbnb's default
vars: 'all', // airbnb's default
varsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))',
args: 'after-used', // airbnb's default
argsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))',
// catch blocks are handled by Unicorns
caughtErrors: 'none',
// caughtErrorsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))',
},
],
};
const importRules = {
'import/namespace': ['error', { allowComputed: true }],
'import/no-absolute-path': 'error',
'import/no-webpack-loader-syntax': 'error',
'import/no-self-import': 'error',
// Enable this sometime in the future when Node.js has ES2015 module support
// 'import/no-cycle': 'error',
// Disabled as it doesn't work with TypeScript
// 'import/newline-after-import': 'error',
'import/no-amd': 'error',
'import/no-duplicates': 'error',
// Enable this sometime in the future when Node.js has ES2015 module support
// 'import/unambiguous': 'error',
// Enable this sometime in the future when Node.js has ES2015 module support
// 'import/no-commonjs': 'error',
// Looks useful, but too unstable at the moment
// 'import/no-deprecated': 'error',
'import/no-extraneous-dependencies': 'off',
'import/no-mutable-exports': 'error',
'import/no-named-as-default-member': 'error',
'import/no-named-as-default': 'error',
// Disabled because it's buggy and it also doesn't work with TypeScript
// 'import/no-unresolved': [
// 'error',
// {
// commonjs: true
// }
// ],
'import/order': 'error',
'import/no-unassigned-import': [
'error',
{ allow: ['@babel/polyfill', '@babel/register'] },
],
'import/prefer-default-export': 'off',
// Ensure more web-compat
// ! note that it doesn't work in CommonJS
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
'import/extensions': 'off',
// ? Always use named exports. Enable?
// 'import/no-default-export': 'error',
// ? enable?
'import/exports-last': 'off',
// todo: Enable in future.
// Ensures everything is tested (all exports should be used).
// For cases when you don't want or can't test, add eslint-ignore comment!
// see: https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unused-modules.md
'import/no-unused-modules': 'off',
'import/no-useless-path-segments': ['error', { noUselessIndex: false }],
};
module.exports = {
env: {
es6: true,
es2020: true,
jest: true,
node: true,
commonjs: true,
},
extends: ['eslint:recommended', 'airbnb-base', 'plugin:prettier/recommended'],
plugins: ['prettier'],
rules: {
...additionalChanges,
...importRules,
},
};
node-formidable-formidable-63c2d93/.github/ 0000775 0000000 0000000 00000000000 15002044507 0020537 5 ustar 00root root 0000000 0000000 node-formidable-formidable-63c2d93/.github/.kodiak.toml 0000664 0000000 0000000 00000001667 15002044507 0022766 0 ustar 00root root 0000000 0000000 # .kodiak.toml
# Minimal config. version is the only required field.
version = 1
[merge]
automerge_label = "ship it"
require_automerge_label = true
block_on_neutral_required_check_runs = true
blocking_labels = ["wip", "do not merge"]
delete_branch_on_merge = true
notify_on_conflict = true
optimistic_updates = false
prioritize_ready_to_merge = true
[merge.message]
title = "pull_request_title"
body = "pull_request_body"
body_type = "markdown"
include_pr_number = true
include_coauthors = true
include_pull_request_url = true
cut_body_after = ""
cut_body_before = ""
[merge.automerge_dependencies]
# only auto merge "minor" and "patch" version upgrades.
# do not automerge "major" version upgrades.
versions = ["minor", "patch"]
usernames = ["dependabot", "renovate"]
[approve]
auto_approve_usernames = ["dependabot", "renovate"]
[update]
always = true
require_automerge_label = true
node-formidable-formidable-63c2d93/.github/dependabot.yml 0000664 0000000 0000000 00000001110 15002044507 0023360 0 ustar 00root root 0000000 0000000 # Versions and updates, dependabot.yml
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
# Maintain dependencies for npm
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
time: "02:00"
# No one cares about dependency labels, they should be auto-merged
labels: []
allow:
# Allow both direct and indirect updates for all packages
- dependency-type: "all"
rebase-strategy: "auto"
# reviewers: []
node-formidable-formidable-63c2d93/.github/workflows/ 0000775 0000000 0000000 00000000000 15002044507 0022574 5 ustar 00root root 0000000 0000000 node-formidable-formidable-63c2d93/.github/workflows/codeql-analysis.yml 0000664 0000000 0000000 00000004444 15002044507 0026415 0 ustar 00root root 0000000 0000000 # For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '0 2 * * *'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
node-formidable-formidable-63c2d93/.github/workflows/main.yml 0000664 0000000 0000000 00000003533 15002044507 0024247 0 ustar 00root root 0000000 0000000 name: ci
# on:
# push:
# branches: [ master ]
# pull_request:
# branches: [ master ]
# jobs:
# # lint:
# # name: Lint
# # runs-on: ubuntu-latest
# # steps:
# # - uses: actions/checkout@v4
# # - name: Set up Node.js
# # uses: actions/setup-node@v4
# # with:
# # node-version: '20'
# # cache: 'npm'
# # - name: Install dependencies
# # run: npm install
# # - name: Run lint
# # run: npm run lint
# test:
# name: Test on ${{ matrix.os }}
# runs-on: ${{ matrix.os }}
# strategy:
# fail-fast: false
# matrix:
# os: [ubuntu-latest, macos-latest]
# node-version: ['lts/*']
# steps:
# - uses: actions/checkout@v4
# - name: Set up Node.js ${{ matrix.node-version }}
# uses: actions/setup-node@v4
# with:
# node-version: ${{ matrix.node-version }}
# cache: 'npm'
# - name: Install dependencies
# run: npm install
# - name: Run tests
# run: npm test
on:
push:
branches:
- '*'
pull_request:
branches:
- '*'
jobs:
build-and-test:
name: Test on ${{ matrix.os }} with Node.js ${{matrix.node-version}}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [18, 20, 22, 'lts/*']
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Run tests
run: pnpm test
node-formidable-formidable-63c2d93/.gitignore 0000664 0000000 0000000 00000003313 15002044507 0021167 0 ustar 00root root 0000000 0000000 # Ignore everything!
*
*~*
# de-ignores: add here what you want to be committed
!logo.png
!logo.jpg
!test-legacy
!tool
!*.*js*
!*.ts*
!*.md*
!.*rc
!.*ignore
!LICENSE
!.editorconfig
!package.json
!yarn.lock
!pnpm-lock.yaml
!**/src
!**/src/**
!**/test
!**/test/**
!**/test-node
!**/test-node/**
!**/*tests*
!**/*tests*/**
!**/.github
!**/.github/**
!**/example*
!**/example*/**
!**/benchmark*
!**/benchmark*/**
# re-ignores: add here what you want to be ignored again
test/tmp
# !src/*.js
# !src/*.ts
# !test
# !test/*.js
# !test/*.ts
# !test/**/*.js
# !test/**/*.ts
# !*/__tests__
# *.tsbuildinfo
# .*cache
# *.cache
# test/tmp
# *.upload
# *.un~
# # Build environment
# dist
# # Package managers lockfiles
# package-lock.json
# shrinkwrap.json
# # Logs
# logs
# *.log
# *~
# # Runtime data
# pids
# *.pid
# *.seed
# *.pid.lock
# # Directory for instrumented libs generated by jscoverage/JSCover
# lib-cov
# # Coverage directory used by tools like istanbul
# /coverage
# # nyc test coverage
# .nyc_output
# # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
# .grunt
# # Bower dependency directory (https://bower.io/)
# bower_components
# # node-waf configuration
# .lock-wscript
# # Compiled binary addons (https://nodejs.org/api/addons.html)
# build/Release
# # Dependency directories
# node_modules/
# jspm_packages/
# # TypeScript v1 declaration files
# typings/
# # Optional npm cache directory
# .npm
# # Optional eslint cache
# .eslintcache
# # Optional REPL history
# .node_repl_history
# # Output of 'npm pack'
# *.tgz
# # Yarn Integrity file
# .yarn-integrity
# # dotenv environment variables file
# .env
# # next.js build output
# .next
benchmark/testuploads/
node-formidable-formidable-63c2d93/.prettierignore 0000664 0000000 0000000 00000003422 15002044507 0022243 0 ustar 00root root 0000000 0000000 # Ignore everything!
*
# de-ignores: add here what you want to be committed
!*.*js*
!*.ts*
!*.md*
!*.y*ml
!**/src
!**/src/**
!**/test
!**/test/**
!**/*tests*
!**/*tests*/**
!**/.github
!**/.github/**
!**/benchmark*
!**/benchmark*/**/*.js
!**/example*
!**/example*/**
# re-ignores: add here what you want to be ignored again
test/tmp
test/fixture/file
test/fixture/http
*.upload
CHANGELOG.md
# CHANGELOG.md
# LICENSE*
# dist
# test/tmp
# test/fixture/http
# test/fixture/file
# test/fixture/multi*
# test/tools
# # fixtures
# # __fixture__
# # __fixtures__
# *.map
# *.lock
# *.js.snap
# coverage
# *.ico
# *.png
# *.svg
# *.jpeg
# *.jpg
# !.all-contributorsrc
# !.*rc.js
# !.verb*.md
# patches
# **/static/**/*.css
# *.tsbuildinfo
# .*cache
# *.cache
# # Package managers lockfiles
# package-lock.json
# shrinkwrap.json
# pnpm-lock.json
# # Logs
# logs
# *.log
# *~
# # Runtime data
# pids
# *.pid
# *.seed
# *.pid.lock
# # Directory for instrumented libs generated by jscoverage/JSCover
# lib-cov
# # Coverage directory used by tools like istanbul
# coverage
# # nyc test coverage
# .nyc_output
# # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
# .grunt
# # Bower dependency directory (https://bower.io/)
# bower_components
# # node-waf configuration
# .lock-wscript
# # Compiled binary addons (https://nodejs.org/api/addons.html)
# build/Release
# # Dependency directories
# node_modules/
# jspm_packages/
# # TypeScript v1 declaration files
# typings/
# # Optional npm cache directory
# .npm
# # Optional eslint cache
# .eslintcache
# # Optional REPL history
# .node_repl_history
# # Output of 'npm pack'
# *.tgz
# # Yarn Integrity file
# .yarn-integrity
# # dotenv environment variables file
# .env
# # next.js build output
# .next
node-formidable-formidable-63c2d93/.prettierrc.js 0000664 0000000 0000000 00000000604 15002044507 0021776 0 ustar 00root root 0000000 0000000 'use strict';
const config = require('@tunnckocore/prettier-config');
module.exports = {
...config,
overrides: [
{
files: ['**/*.md*'],
options: {
proseWrap: 'always',
printWidth: 80,
},
},
{
files: ['**/.all-contributorsrc'],
options: {
parser: 'json-stringify',
singleQuote: false,
},
},
],
};
node-formidable-formidable-63c2d93/.tidelift.yml 0000664 0000000 0000000 00000000316 15002044507 0021604 0 ustar 00root root 0000000 0000000 exceptions:
- name: dot-prop
platform: npm
tests:
- vulnerable
- name: utest
platform: npm
tests:
- unlicensed
- name: only
platform: npm
tests:
- unlicensed
node-formidable-formidable-63c2d93/CHANGELOG.md 0000664 0000000 0000000 00000027173 15002044507 0021022 0 ustar 00root root 0000000 0000000 # Changelog
### 3.5.4
- fix the `os.machine` breaking some dependents, fix [#994](https://github.com/node-formidable/formidable/issues/994)
- add Node 16, 18, 20, 22 to CI/CD
### 3.5.3
- security report by ZAST.AI help for some vulnerabilities addressing (primarily the random names generation)
- update failing tests
- update CI/CD workflows and actions;
- update CodeQL github action for security analysis
- update readme, links and badges
- update to use cuid2 (battle-tested `@paralleldrive/cuid2` package) for better random names - should not be breaking anything since it's still 25 characters long, but a lot safer and faster.
### 3.5.2
* fix: ([#982](https://github.com/node-formidable/formidable/pull/982)) make it easier to import hexoid with webpack
### 3.5.1
* fix: ([#945](https://github.com/node-formidable/formidable/pull/945)) multipart parser fix: flush or fail always (don't hang)
### 3.5.0
* feature: ([#944](https://github.com/node-formidable/formidable/pull/944)) Dual package: Can be imported as ES module and required as commonjs module
### 3.4.0
* feature: ([#940](https://github.com/node-formidable/formidable/pull/940)) form.parse returns a promise if no callback is provided
* it resolves with an array `[fields, files]`
### 3.3.2
* feature: ([#855](https://github.com/node-formidable/formidable/pull/855)) add options.createDirsFromUploads, see README for usage
* form.parse is an async function (ignore the promise)
* benchmarks: add e2e becnhmark with as many request as possible per second
* npm run to display all the commands
* mark as latest on npm
### 3.2.5
* fix: ([#881](https://github.com/node-formidable/formidable/pull/881)) fail earlier when maxFiles is exceeded
### 3.2.4
* fix: ([#857](https://github.com/node-formidable/formidable/pull/857)) improve keep extension
* The code from before 3.2.4 already removed some characters from the file extension. But not always. So it was inconsistent.
* The new code cuts the file extension at the first invalid character (invalid in a file extension).
* The characters that are considered invalid inside a file extension are all except the . numbers and a-Z.
* This change only has an effect if filename option is not used and keepextension option is used
### 3.2.3
* fix: ([#852](https://github.com/node-formidable/formidable/pull/852)) end event is emitted once
### 3.2.2
* refactor: ([#801](https://github.com/node-formidable/formidable/pull/801))
### 3.2.1
* fix: do not let empty file on error ([#796](https://github.com/node-formidable/formidable/pull/796))
* it was probably due to the fact that .destroy on a file stream does not always complete on time
### 3.2.0
* feat: maxFileSize option is now per file (as the name suggests) ([#791](https://github.com/node-formidable/formidable/pull/791))
* feat: add maxFiles option, default Infinity
* feat: add maxTotalFileSize, default is maxFileSize (for backwards compatibility)
* fix: minFileSize is per file
* fix: allowEmptyFiles fix in cases where one file is not empty
* fix: allowEmptyFiles false option by default
* fix: rename wrongly named error
* refactor: rename wrongly named maxFileSize into maxTotalFileSize
### 3.1.5
* fix: PersistentFile.toString ([#796](https://github.com/node-formidable/formidable/pull/796))
### 3.1.4
* fix: add missing pluginFailed error ([#794](https://github.com/node-formidable/formidable/pull/794))
* refactor: use explicit node imports (#786)
### 3.1.1
* feat: handle top level json array, string and number
### 3.1.0
* feat: add firstValues, readBooleans helpers
### 3.0.0
* feat: remove options.multiples ([#730](https://github.com/node-formidable/formidable/pull/730))
* use modern URLSearchParams https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams internally
* files and fields values are always arrays
* fields with [] in the name do not receive special treatment
* remove unused qs and querystring dependency
* feat: Use ES modules ([#727](https://github.com/node-formidable/formidable/pull/727))
* options.enabledPlugins must contain the plugin themselves instead of the plugins names
### 2.0.0
* feat: files are detected if a mimetype is present (previously it was based on filename)
* 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)
* 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: 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)
* fix(tests): include multipart and qs parser unit tests, part of [#415](https://github.com/node-formidable/node-formidable/issues/415)
* fix: reorganize exports + move parsers to `src/parsers/`
* fix: update docs and examples [#544](https://github.com/node-formidable/node-formidable/pull/544) ([#248](https://github.com/node-formidable/node-formidable/issues/248), [#335](https://github.com/node-formidable/node-formidable/issues/335), [#371](https://github.com/node-formidable/node-formidable/issues/371), [#372](https://github.com/node-formidable/node-formidable/issues/372), [#387](https://github.com/node-formidable/node-formidable/issues/387), partly [#471](https://github.com/node-formidable/node-formidable/issues/471), [#535](https://github.com/node-formidable/node-formidable/issues/535))
* 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))
* 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)
* `maxFileSize` option with default of 200MB (Charlike Mike Reagent, Nima Shahri)
* Simplified buffering in JSON parser to avoid denial of service attack (Kornel)
* Fixed upload file cleanup on aborted requests (liaoweiqiang)
* Fixed error handling of closed _writeStream (Vitalii)
### v1.1.1 (2017-01-15)
* Fix DeprecationWarning about os.tmpDir() (Christian)
* Update `buffer.write` order of arguments for Node 7 (Kornel Lesiński)
* JSON Parser emits error events to the IncomingForm (alessio.montagnani)
* Improved Content-Disposition parsing (Sebastien)
* Access WriteStream of fs during runtime instead of include time (Jonas Amundsen)
* Use built-in toString to convert buffer to hex (Charmander)
* Add hash to json if present (Nick Stamas)
* Add license to package.json (Simen Bekkhus)
### v1.0.14 (2013-05-03)
* Add failing hash tests. (Ben Trask)
* Enable hash calculation again (Eugene Girshov)
* Test for immediate data events (Tim Smart)
* Re-arrange IncomingForm#parse (Tim Smart)
### v1.0.13
* Only update hash if update method exists (Sven Lito)
* According to travis v0.10 needs to go quoted (Sven Lito)
* Bumping build node versions (Sven Lito)
* Additional fix for empty requests (Eugene Girshov)
* Change the default to 1000, to match the new Node behaviour. (OrangeDog)
* Add ability to control maxKeys in the querystring parser. (OrangeDog)
* Adjust test case to work with node 0.9.x (Eugene Girshov)
* Update package.json (Sven Lito)
* Path adjustment according to eb4468b (Markus Ast)
### v1.0.12
* Emit error on aborted connections (Eugene Girshov)
* Add support for empty requests (Eugene Girshov)
* Fix name/filename handling in Content-Disposition (jesperp)
* Tolerate malformed closing boundary in multipart (Eugene Girshov)
* Ignore preamble in multipart messages (Eugene Girshov)
* Add support for application/json (Mike Frey, Carlos Rodriguez)
* Add support for Base64 encoding (Elmer Bulthuis)
* Add File#toJSON (TJ Holowaychuk)
* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley)
* Documentation improvements (Sven Lito, Andre Azevedo)
* Add support for application/octet-stream (Ion Lupascu, Chris Scribner)
* Use os.tmpdir() to get tmp directory (Andrew Kelley)
* Improve package.json (Andrew Kelley, Sven Lito)
* Fix benchmark script (Andrew Kelley)
* Fix scope issue in incoming_forms (Sven Lito)
* Fix file handle leak on error (OrangeDog)
---
[First commit, #3270eb4b1f8b (May 4th, 2010)](https://github.com/node-formidable/formidable/commit/3270eb4b1f8bb667b8c12f64c36a4e7b854216d8)
node-formidable-formidable-63c2d93/LICENSE 0000664 0000000 0000000 00000002131 15002044507 0020201 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2011-present Felix Geisendörfer, and contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
node-formidable-formidable-63c2d93/README.md 0000664 0000000 0000000 00000113245 15002044507 0020464 0 ustar 00root root 0000000 0000000
# 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]
> A Node.js module for parsing form data, especially file uploads.
[![Code style][codestyle-img]][codestyle-url]
[![linux build status][linux-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. For bugs reports and feature requests, [please create an
issue][open-issue-url] or ping [@wgw_eth / @wgw_lol][twitter-url]
at Twitter.
[![Conventional Commits][ccommits-img]][ccommits-url]
[![Minimum Required Nodejs][nodejs-img]][npmv-url]
[![Buy me a Kofi][kofi-img]][kofi-url]
[![Make A Pull Request][prs-welcome-img]][prs-welcome-url]
This project is [semantically versioned](https://semver.org) and if you want support in migrating between versions you can schedule us for training or support us through donations, so we can prioritize.
> [!CAUTION]
> As of April 2025, old versions like v1 and v2 are still the most used, while they are deperecated for years -- they are also vulnerable to attacks if you are not implementing it properly. **Please upgrade!** We are here to help, and AI Editors & Agents could help a lot in such codemod-like migrations.
> [!TIP]
> If you are starting a fresh project, you can check out the `formidable-mini` which is a super minimal version of Formidable (not quite configurable yet, but when it does it could become the basis for `formidable@v4`), using web standards like FormData API and File API, and you can use it to stream uploads directly to S3 or other such services.
[![][npm-weekly-img]][npmv-url] [![][npm-monthly-img]][npmv-url]
[![][npm-yearly-img]][npmv-url] [![][npm-alltime-img]][npmv-url]
## Project Status: Maintained
> [!NOTE]
> 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
[**@felixge**](https://github.com/felixge) for
[Transloadit](http://transloadit.com/), a service focused on uploading and
encoding images and videos. It has been battle-tested against hundreds of GBs of
file uploads from a large variety of clients and is considered production-ready
and is used in production for years.
Currently, we are few maintainers trying to deal with it. :) More contributors
are always welcome! :heart: Jump on
[issue #412](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.
## Highlights
- [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
- Graceful error handling
- Very high test coverage
## Install
This package is a dual ESM/commonjs package.
> [!NOTE]
> This project requires `Node.js >= 20`. Install it using [yarn](https://yarnpkg.com) or [npm](https://npmjs.com). _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.
```
# v2
npm install formidable@v2
# v3
npm install formidable
npm install formidable@v3
```
_**Note:** Future not ready releases will be published on `*-next` dist-tags for the corresponding version._
## Examples
For more examples look at the `examples/` directory.
### with Node.js http module
Parse an incoming file upload, with the
[Node.js's built-in `http` module](https://nodejs.org/api/http.html).
```js
import http from 'node:http';
import formidable, {errors as formidableErrors} from 'formidable';
const server = http.createServer(async (req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({});
let fields;
let files;
try {
[fields, files] = await form.parse(req);
} catch (err) {
// example to check for a very specific error
if (err.code === formidableErrors.maxFieldsExceeded) {
}
console.error(err);
res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
res.end(String(err));
return;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ fields, files }, null, 2));
return;
}
// show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
With Node.js "http" module
`);
});
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
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 ...');
});
```
### 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
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 ...');
});
```
## Benchmarks
The benchmark is quite old, from the old codebase. But maybe quite true though.
Previously the numbers was around ~500 mb/sec. Currently with moving to the new
Node.js Streams API it's faster. You can clearly see the differences between the
Node versions.
_Note: a lot better benchmarking could and should be done in future._
Benchmarked on 8GB RAM, Xeon X3440 (2.53 GHz, 4 cores, 8 threads)
```
~/github/node-formidable master
❯ nve --parallel 8 10 12 13 node benchmark/bench-multipart-parser.js
⬢ Node 8
1261.08 mb/sec
⬢ Node 10
1113.04 mb/sec
⬢ Node 12
2107.00 mb/sec
⬢ Node 13
2566.42 mb/sec
```

## API
### 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);
```
### 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;
```
#### `options.filter` **{function}** function ({name, originalFilename, mimetype}) -> boolean
Behaves like Array.filter: Returning false will simply ignore the file and go to the next.
```js
const options = {
filter: function ({name, originalFilename, mimetype}) {
// keep only images
return mimetype && mimetype.includes("image");
}
};
```
**Note:** use an outside variable to cancel all uploads upon the first error
**Note:** use form.emit('error') to make form.parse error
```js
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;
}
};
```
### .parse(request, ?callback)
Parses an incoming Node.js `request` containing form data. If `callback` is not provided a promise is returned.
```js
const form = formidable({ uploadDir: __dirname });
form.parse(req, (err, fields, files) => {
console.log('fields:', fields);
console.log('files:', files);
});
// with Promise
const [fields, files] = await form.parse(req);
```
You may overwrite this method if you are interested in directly accessing the
multipart stream. Doing so will disable any `'field'` / `'file'` events
processing which would occur otherwise, making you fully responsible for
handling the processing.
About `uploadDir`, given the following directory structure
```
project-name
├── src
│ └── server.js
│
└── uploads
└── image.jpg
```
`__dirname` would be the same directory as the source file itself (src)
```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
`data` listener, so you can do whatever you choose there, based on whether its
before the file been emitted, the header value, the header name, on field, on
file and etc.
Or the other way could be to just override the `form.onPart` as it's shown a bit
later.
```js
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);
}
});
```
### .use(plugin: Plugin)
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.
```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
```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.onPart
If you want to use Formidable to only handle certain parts for you, you can do
something similar. Or see
[#387](https://github.com/node-formidable/node-formidable/issues/387) for
inspiration, you can for example validate the mime-type.
```js
const form = formidable();
form.onPart = (part) => {
part.on('data', (buffer) => {
// do whatever you want here
});
};
```
For example, force Formidable to be used only on non-file "parts" (i.e., html
fields)
```js
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);
}
};
```
### File
```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.
### 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 =`
```js
form.on('progress', (bytesReceived, bytesExpected) => {});
```
#### `'field'`
Emitted whenever a field / value pair has been received.
```js
form.on('field', (name, value) => {});
```
#### `'fileBegin'`
Emitted whenever a new file is detected in the upload stream. Use this event if
you want to stream the file to somewhere else while buffering the upload on the
file system.
```js
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
});
```
#### `'file'`
Emitted whenever a field / file pair has been received. `file` is an instance of
`File`.
```js
form.on('file', (formname, file) => {
// same as fileBegin, except
// it is too late to change file.filepath
// file.hash is available if options.hash was used
});
```
#### `'error'`
Emitted when there is an error processing the incoming form. A request that
experiences an error is automatically paused, you will have to manually call
`request.resume()` if you want the request to continue firing `'data'` events.
May have `error.httpCode` and `error.code` attached.
```js
form.on('error', (err) => {});
```
#### `'aborted'`
Emitted when the request was aborted by the user. Right now this can be due to a
'timeout' or 'close' event on the socket. After this event is emitted, an
`error` event will follow. In the future there will be a separate 'timeout'
event (needs a change in the node core).
```js
form.on('aborted', () => {});
```
#### `'end'`
Emitted when the entire request has been received, and all contained files have
finished flushing to disk. This is a great place for you to send your response.
```js
form.on('end', () => {});
```
### Helpers
#### firstValues
Gets first values of fields, like pre 3.0.0 without multiples pass in a list of optional exceptions where arrays of strings is still wanted (`