pax_global_header 0000666 0000000 0000000 00000000064 15266374662 0014533 g ustar 00root root 0000000 0000000 52 comment=2c380d06cdaacc68bbef8b36244493a3d33d6b88 expressjs-multer-2c380d0/ 0000775 0000000 0000000 00000000000 15266374662 0015414 5 ustar 00root root 0000000 0000000 expressjs-multer-2c380d0/.gitattributes 0000664 0000000 0000000 00000000521 15266374662 0020305 0 ustar 00root root 0000000 0000000 # The upload fixtures are opaque payloads whose exact byte size the tests assert # on. Treating them as binary keeps Git's end-of-line conversion from rewriting # LF to CRLF when they are checked out on Windows, which would inflate the size # of every text-like fixture and fail the tests that hardcode those sizes. test/files/** binary expressjs-multer-2c380d0/.github/ 0000775 0000000 0000000 00000000000 15266374662 0016754 5 ustar 00root root 0000000 0000000 expressjs-multer-2c380d0/.github/dependabot.yml 0000664 0000000 0000000 00000000504 15266374662 0021603 0 ustar 00root root 0000000 0000000 version: 2 updates: - package-ecosystem: github-actions directory: / schedule: interval: monthly - package-ecosystem: npm directory: / schedule: interval: monthly open-pull-requests-limit: 10 ignore: - dependency-name: "*" update-types: ["version-update:semver-major"] expressjs-multer-2c380d0/.github/workflows/ 0000775 0000000 0000000 00000000000 15266374662 0021011 5 ustar 00root root 0000000 0000000 expressjs-multer-2c380d0/.github/workflows/ci.yml 0000664 0000000 0000000 00000014475 15266374662 0022142 0 ustar 00root root 0000000 0000000 name: ci on: push: branches: - main pull_request: permissions: contents: read jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: lts/* - name: Install Node.js dependencies run: npm install - name: Lint code run: npm run lint test: permissions: checks: write # for coverallsapp/github-action to create new checks contents: read # for actions/checkout to fetch code runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: - ubuntu-latest - windows-latest name: - Node.js 10.x - Node.js 11.x - Node.js 12.x - Node.js 13.x - Node.js 14.x - Node.js 15.x - Node.js 16.x - Node.js 17.x - Node.js 18.x - Node.js 19.x - Node.js 20.x - Node.js 21.x - Node.js 22.x - Node.js 23.x - Node.js 24.x - Node.js 25.x - Node.js 26.x include: - name: Node.js 10.x node-version: "10.16.0" npm-i: mocha@8.4.0 - name: Node.js 11.x node-version: "11.15" npm-i: mocha@8.4.0 - name: Node.js 12.x node-version: "12.0.0" npm-i: mocha@9.2.2 - name: Node.js 13.x node-version: "13.14" npm-i: mocha@9.2.2 - name: Node.js 14.x node-version: "14.0.0" npm-i: mocha@9.2.2 - name: Node.js 15.x node-version: "15.0.0" npm-i: mocha@9.2.2 - name: Node.js 16.x node-version: "16.0.0" - name: Node.js 17.x node-version: "17.0.0" - name: Node.js 18.x node-version: "18.0.0" - name: Node.js 19.x node-version: "19.0.0" - name: Node.js 20.x node-version: "20.0.0" - name: Node.js 21.x node-version: "21" - name: Node.js 22.x node-version: "22" - name: Node.js 23.x node-version: "23" - name: Node.js 24.x node-version: "24" - name: Node.js 25.x node-version: "25" - name: Node.js 26.x node-version: "26" # Windows on Node.js < 22 is not yet stable in the test suite; # keep those legs informational until it is. - name: Node.js 10.x os: windows-latest experimental: true - name: Node.js 11.x os: windows-latest experimental: true - name: Node.js 12.x os: windows-latest experimental: true - name: Node.js 13.x os: windows-latest experimental: true - name: Node.js 14.x os: windows-latest experimental: true - name: Node.js 15.x os: windows-latest experimental: true - name: Node.js 16.x os: windows-latest experimental: true - name: Node.js 17.x os: windows-latest experimental: true - name: Node.js 18.x os: windows-latest experimental: true - name: Node.js 19.x os: windows-latest experimental: true - name: Node.js 20.x os: windows-latest experimental: true - name: Node.js 21.x os: windows-latest experimental: true # macOS legs come from `include`, scoped to versions that can run on # the macOS runners: Node.js < 16 has no darwin-arm64 builds (setup-node # cannot install them natively and those legs would be permanently # red), so they are skipped. 16.x-21.x run as x64 under Rosetta; # informational until measured, mirroring the Windows < 22 treatment. - name: Node.js 16.x os: macos-latest experimental: true - name: Node.js 17.x os: macos-latest experimental: true - name: Node.js 18.x os: macos-latest experimental: true - name: Node.js 19.x os: macos-latest experimental: true - name: Node.js 20.x os: macos-latest experimental: true - name: Node.js 21.x os: macos-latest experimental: true - name: Node.js 22.x os: macos-latest - name: Node.js 23.x os: macos-latest - name: Node.js 24.x os: macos-latest - name: Node.js 25.x os: macos-latest - name: Node.js 26.x os: macos-latest continue-on-error: ${{ matrix.experimental == true }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Node.js ${{ matrix.node-version }} uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: ${{ matrix.node-version }} - name: Remove npm module(s) ${{ matrix.npm-rm }} run: npm rm --silent --save-dev ${{ matrix.npm-rm }} if: matrix.npm-rm != '' - name: Install npm module(s) ${{ matrix.npm-i }} run: npm install --save-dev ${{ matrix.npm-i }} if: matrix.npm-i != '' - name: Install Node.js dependencies run: npm install - name: List environment shell: bash run: | echo "node@$(node -v)" echo "npm@$(npm -v)" npm -s ls ||: - name: Run tests shell: bash run: npm run test-ci - name: Collect code coverage uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2.3.8 if: matrix.os == 'ubuntu-latest' with: github-token: ${{ secrets.GITHUB_TOKEN }} flag-name: run-${{ matrix.name }} parallel: true coverage: permissions: checks: write # for coverallsapp/github-action to create new checks needs: test runs-on: ubuntu-latest steps: - name: Upload code coverage uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2.3.8 with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true expressjs-multer-2c380d0/.github/workflows/codeql.yml 0000664 0000000 0000000 00000004655 15266374662 0023015 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: ["main", "v2"] pull_request: # The branches below must be a subset of the branches above branches: ["main", "v2"] schedule: - cron: "0 0 * * 1" permissions: contents: read jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 with: languages: javascript # 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. # 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@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 # ℹ� Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun # If the Autobuild fails above, remove it and uncomment the following three lines. # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. # - run: | # echo "Run, Build Application using script" # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 with: category: "/language:javascript" expressjs-multer-2c380d0/.github/workflows/npm-publish.yml 0000664 0000000 0000000 00000001536 15266374662 0023777 0 ustar 00root root 0000000 0000000 name: Publish package to npm on: release: types: [created] concurrency: group: "${{ github.workflow }} ✨ ${{ github.ref }}" cancel-in-progress: false permissions: contents: read jobs: publish: name: Publish to npm runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "lts/*" registry-url: "https://registry.npmjs.org" # npm stage publish requires npm >= 11.15.0 - name: Upgrade npm run: npm install -g npm@latest - name: Stage publish to npm run: npm stage publish expressjs-multer-2c380d0/.github/workflows/scorecard.yml 0000664 0000000 0000000 00000005657 15266374662 0023516 0 ustar 00root root 0000000 0000000 # This workflow uses actions that are not certified by GitHub. They are provided # by a third-party and are governed by separate terms of service, privacy # policy, and support documentation. name: Scorecard supply-chain security on: # For Branch-Protection check. Only the default branch is supported. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection branch_protection_rule: # To guarantee Maintained check is occasionally updated. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained schedule: - cron: '16 21 * * 1' push: branches: [ "main" ] # Declare default permissions as read only. permissions: read-all jobs: analysis: name: Scorecard analysis runs-on: ubuntu-latest permissions: # Needed to upload the results to code-scanning dashboard. security-events: write # Needed to publish results and get a badge (see publish_results below). id-token: write # Uncomment the permissions below if installing in a private repository. # contents: read # actions: read steps: - name: "Checkout code" uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: "Run analysis" uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4 with: results_file: results.sarif results_format: sarif # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: # - you want to enable the Branch-Protection check on a *public* repository, or # - you are installing Scorecard on a *private* repository # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. # repo_token: ${{ secrets.SCORECARD_TOKEN }} # Public repositories: # - Publish results to OpenSSF REST API for easy access by consumers # - Allows the repository to include the Scorecard badge. # - See https://github.com/ossf/scorecard-action#publishing-results. # For private repositories: # - `publish_results` will always be set to `false`, regardless # of the value entered here. publish_results: true # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: SARIF file path: results.sarif retention-days: 5 # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 with: sarif_file: results.sarif expressjs-multer-2c380d0/.gitignore 0000664 0000000 0000000 00000000260 15266374662 0017402 0 ustar 00root root 0000000 0000000 # OS X .DS_Store* Icon? ._* # Windows Thumbs.db ehthumbs.db Desktop.ini # Linux .directory *~ # npm node_modules *.log *.gz # Coverage & Test Output coverage .nyc_output expressjs-multer-2c380d0/.npmrc 0000664 0000000 0000000 00000000023 15266374662 0016527 0 ustar 00root root 0000000 0000000 package-lock=false expressjs-multer-2c380d0/CHANGELOG.md 0000664 0000000 0000000 00000023663 15266374662 0017237 0 ustar 00root root 0000000 0000000 # Change log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## 2.5.0 - Fix [CVE-2026-113872](https://www.cve.org/CVERecord?id=CVE-2026-113872) ([GHSA-q7qp-rjg7-q26m](https://github.com/expressjs/multer/security/advisories/GHSA-q7qp-rjg7-q26m)) - Accept a field value of exactly `limits.fieldSize` bytes, so `LIMIT_FIELD_VALUE` fires only when the limit is exceeded. This also covers the default `fieldSize` of 1MB, so a 1048576 byte value is no longer rejected when you set no limits. If you set `fieldSize` one higher to work around this, you can drop the extra one ([#1481](https://github.com/expressjs/multer/pull/1481)) - Do not add a file to the abort cleanup list when its storage engine reports an error after a `LIMIT_FILE_SIZE` abort; `DiskStorage` no longer tries to unlink an undefined path ([#1489](https://github.com/expressjs/multer/pull/1489)) ## 2.4.0 - Fix [CVE-2026-88932](https://www.cve.org/CVERecord?id=CVE-2026-88932) ([GHSA-3pph-fpjx-jg34](https://github.com/expressjs/multer/security/advisories/GHSA-3pph-fpjx-jg34)) - Add `filename` to `LIMIT_FILE_SIZE` and `LIMIT_UNEXPECTED_FILE` errors ([#1416](https://github.com/expressjs/multer/pull/1416)) - Accept a function for `limits`, called with the request, to set limits per request ([#1133](https://github.com/expressjs/multer/pull/1133)) - Add opt-in `flush` option to `DiskStorage` to fsync files before the callback runs ([#1458](https://github.com/expressjs/multer/pull/1458)) - Expose busboy's `defCharset`, `highWaterMark` and `fileHwm` options ([#1465](https://github.com/expressjs/multer/pull/1465)) - Add `streamHandler` option to feed busboy from pre-consumed bodies (Google Cloud Functions, Firebase) ([#1466](https://github.com/expressjs/multer/pull/1466)) - Allow `multer.diskStorage()` to be called without options ([#1471](https://github.com/expressjs/multer/pull/1471)) - Decode WHATWG-escaped characters (`%0A`, `%0D`, `%22`) in field names, matching `file.originalname` since 2.3.0: `req.body` keys, `file.fieldname` and `err.field` now carry the real name. If you matched the escaped spelling as a workaround, use the real name now ([#1473](https://github.com/expressjs/multer/pull/1473)) - Report the decoded filename in `err.filename` on `LIMIT_FILE_SIZE` errors, matching `file.originalname` ([#1478](https://github.com/expressjs/multer/pull/1478)) - Reject non-integer or negative `limits` values at construction time; a float limit silently disabled the check ([#1395](https://github.com/expressjs/multer/pull/1395), [#1335](https://github.com/expressjs/multer/pull/1335)) - Accept requests with exactly `limits.parts` parts; `LIMIT_PART_COUNT` now fires only when the limit is exceeded. If you set `parts` one higher to work around this, you can drop the extra one ([#1446](https://github.com/expressjs/multer/pull/1446)) - Files skipped by `fileFilter` no longer count towards `maxCount` ([#1426](https://github.com/expressjs/multer/pull/1426)) - Change the `LIMIT_UNEXPECTED_FILE` message to "Unexpected file field" ([#426](https://github.com/expressjs/multer/pull/426)) - Remove the `concat-stream` dependency ([#1356](https://github.com/expressjs/multer/pull/1356)) - Docs: add JSDoc to the public API and document the storage engine stream contract ([#1467](https://github.com/expressjs/multer/pull/1467), [#1468](https://github.com/expressjs/multer/pull/1468)) - Docs: add FormData upload examples ([#896](https://github.com/expressjs/multer/pull/896)) - Docs: remove the translated READMEs ([#1463](https://github.com/expressjs/multer/pull/1463)) - Internal: run the test suite on macOS ([#1464](https://github.com/expressjs/multer/pull/1464)) ## 2.3.0 - Fix [CVE-2026-77078](https://www.cve.org/CVERecord?id=CVE-2026-77078) ([GHSA-wc9g-mqfw-jrwm](https://github.com/expressjs/multer/security/advisories/GHSA-wc9g-mqfw-jrwm)) - Fix [CVE-2026-77037](https://www.cve.org/CVERecord?id=CVE-2026-77037) ([GHSA-qfvm-cv95-jqjf](https://github.com/expressjs/multer/security/advisories/GHSA-qfvm-cv95-jqjf)) - Fix [CVE-2026-77063](https://www.cve.org/CVERecord?id=CVE-2026-77063) ([GHSA-qvfw-j98x-7q72](https://github.com/expressjs/multer/security/advisories/GHSA-qvfw-j98x-7q72)) - Fix [CVE-2026-82333](https://www.cve.org/CVERecord?id=CVE-2026-82333) ([GHSA-535w-7cp7-47q4](https://github.com/expressjs/multer/security/advisories/GHSA-535w-7cp7-47q4)) - Add `MulterError` codes `INVALID_FIELD_NAME` and `STREAM_DESTROYED` - Add opt-in `limits.fieldArrayIndexLimit` to bound numeric array indexes in field names ([#1438](https://github.com/expressjs/multer/pull/1438)) - Accept files whose size is exactly `limits.fileSize` ([#1407](https://github.com/expressjs/multer/pull/1407)) - Preserve the caller's async context (`AsyncLocalStorage`) when calling `next()` ([#1124](https://github.com/expressjs/multer/pull/1124)) - Decode WHATWG-escaped characters (`%0A`, `%0D`, `%22`) in `file.originalname` ([#1421](https://github.com/expressjs/multer/pull/1421)) - Do not crash when `fileFilter` invokes its callback more than once ([#1427](https://github.com/expressjs/multer/pull/1427)) - Use a fallback message for `MulterError` codes without a mapping ([#1448](https://github.com/expressjs/multer/pull/1448)) - Docs: clarify `preservePath` and `parts`, use `crypto.randomBytes` in the `DiskStorage` example ([#1414](https://github.com/expressjs/multer/pull/1414), [#1430](https://github.com/expressjs/multer/pull/1430), [#1436](https://github.com/expressjs/multer/pull/1436)) - Docs: add Indonesian, Japanese and Tamil translations and refresh all translations from the current README ([#1431](https://github.com/expressjs/multer/pull/1431), [#1354](https://github.com/expressjs/multer/pull/1354), [#1462](https://github.com/expressjs/multer/pull/1462)) - Internal: run the test suite on Windows ([#1334](https://github.com/expressjs/multer/pull/1334)) ## 2.2.0 - Fix [CVE-2026-5038](https://www.cve.org/CVERecord?id=CVE-2026-5038) ([GHSA-3p4h-7m6x-2hcm](https://github.com/expressjs/multer/security/advisories/GHSA-3p4h-7m6x-2hcm)) - Fix [CVE-2026-5079](https://www.cve.org/CVERecord?id=CVE-2026-5079) ([GHSA-72gw-mp4g-v24j](https://github.com/expressjs/multer/security/advisories/GHSA-72gw-mp4g-v24j)) ## 2.1.1 - Fix [CVE-2026-3520](https://www.cve.org/CVERecord?id=CVE-2026-3520) ([GHSA-5528-5vmv-3xc2](https://github.com/expressjs/multer/security/advisories/GHSA-5528-5vmv-3xc2)) - fix error/abort handling ## 2.1.0 - Add `defParamCharset` option for UTF-8 filename support ([#1210](https://github.com/expressjs/multer/pull/1210)) - Fix [CVE-2026-2359](https://www.cve.org/CVERecord?id=CVE-2026-2359) ([GHSA-v52c-386h-88mc](https://github.com/expressjs/multer/security/advisories/GHSA-v52c-386h-88mc)) - Fix [CVE-2026-3304](https://www.cve.org/CVERecord?id=CVE-2026-3304) ([GHSA-xf7r-hgr6-v32p](https://github.com/expressjs/multer/security/advisories/GHSA-xf7r-hgr6-v32p)) ## 2.0.2 - Fix [CVE-2025-7338](https://www.cve.org/CVERecord?id=CVE-2025-7338) ([GHSA-fjgf-rc76-4x9p](https://github.com/expressjs/multer/security/advisories/GHSA-fjgf-rc76-4x9p)) ## 2.0.1 - Fix [CVE-2025-48997](https://www.cve.org/CVERecord?id=CVE-2025-48997) ([GHSA-g5hg-p3ph-g8qg](https://github.com/expressjs/multer/security/advisories/GHSA-g5hg-p3ph-g8qg)) ## 2.0.0 - **Breaking change: The minimum supported Node version is now 10.16.0** - Fix [CVE-2025-47935](https://www.cve.org/CVERecord?id=CVE-2025-47935) ([GHSA-44fp-w29j-9vj5](https://github.com/expressjs/multer/security/advisories/GHSA-44fp-w29j-9vj5)) - Fix [CVE-2025-47944](https://www.cve.org/CVERecord?id=CVE-2025-47944) ([GHSA-4pg4-qvpc-4q3h](https://github.com/expressjs/multer/security/advisories/GHSA-4pg4-qvpc-4q3h)) ## 1.4.5-lts.2 - Fix out-of-band error event from busboy (#1177) ## 1.4.5-lts.1 - No changes ## 1.4.4-lts.1 - Bugfix: Bump busboy to fix CVE-2022-24434 (#1097) - Breaking: Require Node.js 10.16.0 or later (#1097) ## 1.4.4 - 2021-12-07 - Bugfix: Handle missing field names (#913) - Docs: Add Vietnamese translation (#803) - Docs: Improve Spanish translation (#948) ## 1.4.3 - 2021-08-09 - Bugfix: Avoid deprecated pseudoRandomBytes function (#774) - Docs: Add Português Brazil translation for README (#758) - Docs: Clarify the callback calling convention (#775) - Docs: Add example on how to link to html multipart form (#580) - Docs: Add Spanish translation for README (#838) - Docs: Add Math.random() to storage filename example (#841) - Docs: Fix mistakes in russian doc (#869) - Docs: Improve Português Brazil translation (#877) - Docs: Update var to const in all Readmes (#1024) - Internal: Bump mkdirp version (#862) - Internal: Bump Standard version (#878) ## 1.4.2 - 2019-07-16 - Docs: Add Russian translation for README (#662) - Docs: Patch zh-CN README base on newest README (#670) - Docs: Fix broken link in Readme (#679) - Docs: Fix broken link in Chinese Readme (#730) - Docs: Fix typo in Russian README (#738) - Docs: Add unit for fieldSize in busboy limit params (#734) - Internal: Make unit tests compatible with Node.js 13.x (#752) ## 1.4.1 - 2018-10-11 - Bugfix: Make sure that req.file.buffer always is a Buffer ## 1.4.0 - 2018-09-26 - Feature: Make Multer errors inherit from MulterError ## 1.3.1 - 2018-06-28 - Bugfix: Bump vulnerable dependency ## 1.3.0 - 2017-01-25 - Feature: Expose preservePath option ## 1.2.1 - 2016-12-14 - Bugfix: Prevent Multiple Errors from Crashing ## 1.2.0 - 2016-08-04 - Feature: add .none() for accepting only fields ## 1.1.0 - 2015-10-23 - Feature: accept any file, regardless of fieldname ## 1.0.6 - 2015-10-03 - Bugfix: always report limit errors ## 1.0.5 - 2015-09-19 - Bugfix: drain the stream before considering request done ## 1.0.4 - 2015-09-19 - Bugfix: propagate all errors from busboy ## 1.0.3 - 2015-08-06 - Bugfix: ensure file order is correct ## 1.0.2 - 2015-08-06 - Bugfix: don't hang when hitting size limit ## 1.0.1 - 2015-07-20 - Bugfix: decrement pending writes on error ## 1.0.0 - 2015-07-18 - Introduce storage engines - Specify expected fields - Follow the W3C JSON form spec expressjs-multer-2c380d0/LICENSE 0000664 0000000 0000000 00000002131 15266374662 0016416 0 ustar 00root root 0000000 0000000 Copyright (c) 2014 Hage Yaapa <[http://www.hacksparrow.com](http://www.hacksparrow.com)> 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. expressjs-multer-2c380d0/README.md 0000664 0000000 0000000 00000037770 15266374662 0016711 0 ustar 00root root 0000000 0000000 # Multer [![NPM Version][npm-version-image]][npm-url] [![NPM Downloads][npm-downloads-image]][npm-url] [![Build Status][ci-image]][ci-url] [![Test Coverage][test-image]][test-url] [![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer] Multer is a node.js middleware for handling `multipart/form-data`, which is primarily used for uploading files. It is written on top of [busboy](https://github.com/mscdex/busboy) for maximum efficiency. **NOTE**: Multer will not process any form which is not multipart (`multipart/form-data`). ## Installation ```sh $ npm install multer ``` ## Usage Multer adds a `body` object and a `file` or `files` object to the `request` object. The `body` object contains the values of the text fields of the form, the `file` or `files` object contains the files uploaded via the form. Basic usage example: Don't forget the `enctype="multipart/form-data"` in your form. ```html
``` ```javascript const express = require('express') const multer = require('multer') const upload = multer({ dest: 'uploads/' }) const app = express() app.post('/profile', upload.single('avatar'), function (req, res, next) { // req.file is the `avatar` file // req.body will hold the text fields, if there were any }) app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) { // req.files is array of `photos` files // req.body will contain the text fields, if there were any }) const uploadMiddleware = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }]) app.post('/cool-profile', uploadMiddleware, function (req, res, next) { // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files // // e.g. // req.files['avatar'][0] -> File // req.files['gallery'] -> Array // // req.body will contain the text fields, if there were any }) ``` In case you need to handle a text-only multipart form, you should use the `.none()` method: ```javascript const express = require('express') const app = express() const multer = require('multer') const upload = multer() app.post('/profile', upload.none(), function (req, res, next) { // req.body contains the text fields }) ``` Here's an example on how multer is used in a HTML form. Take special note of the `enctype="multipart/form-data"` and `name="uploaded_file"` fields: ```html ``` Then in your javascript file you would add these lines to access both the file and the body. It is important that you use the `name` field value from the form in your upload function. This tells multer which field on the request it should look for the files in. If these fields aren't the same in the HTML form and on your server, your upload will fail: ```javascript const multer = require('multer') const upload = multer({ dest: './public/data/uploads/' }) app.post('/stats', upload.single('uploaded_file'), function (req, res) { // req.file is the name of your file in the form above, here 'uploaded_file' // req.body will hold the text fields, if there were any console.log(req.file, req.body) }); ``` Complete client-side and server-side examples (browser `FormData` uploads of a blob and of an image) are in the [`examples/`](examples/) folder. ## API ### File information Each file contains the following information: Key | Description | Note --- | --- | --- `fieldname` | Field name specified in the form | `originalname` | Name of the file on the user's computer, or the full path when `preservePath: true` | `encoding` | Encoding type of the file | `mimetype` | Mime type of the file | `size` | Size of the file in bytes | `destination` | The folder to which the file has been saved | `DiskStorage` `filename` | The name of the file within the `destination` | `DiskStorage` `path` | The full path to the uploaded file | `DiskStorage` `buffer` | A `Buffer` of the entire file | `MemoryStorage` ### `multer(opts)` Multer accepts an options object, the most basic of which is the `dest` property, which tells Multer where to upload the files. In case you omit the options object, the files will be kept in memory and never written to disk. By default, Multer will rename the files so as to avoid naming conflicts. The renaming function can be customized according to your needs. The following are the options that can be passed to Multer. Key | Description --- | --- `defCharset` | Default character set to use for text field values that do not declare one. Default: `'utf8'` `defParamCharset` | Default character set to use for values of part header parameters (e.g. filename) that are not extended parameters (that contain an explicit charset). Default: `'latin1'` `dest` or `storage` | Where to store the files `fileFilter` | Function to control which files are accepted `fileHwm` | `highWaterMark` of each file stream (`file.stream`). Default: busboy's default `highWaterMark` | `highWaterMark` of the multipart parser stream. Default: busboy's default `limits` | Limits of the uploaded data `preservePath` | Keep the full client-supplied path in `file.originalname` instead of just the base name `streamHandler` | Function that feeds the request body to busboy; defaults to `req.pipe(busboy)` In an average web app, only `dest` might be required, and configured as shown in the following example. ```javascript const upload = multer({ dest: 'uploads/' }) ``` When `preservePath` is enabled, Multer passes the incoming filename through with any path segments provided by the client. This is exposed as `file.originalname`; it does not change the destination folder, create directories, or sanitize the path for you. `file.originalname` is always client-supplied and should be treated as untrusted; with `preservePath` it additionally contains the path segments the client sent. Normalize or validate it before using it in a custom `filename` or storage engine. If you want more control over your uploads, you'll want to use the `storage` option instead of `dest`. Multer ships with storage engines `DiskStorage` and `MemoryStorage`; More engines are available from third parties. #### `.single(fieldname)` Accept a single file with the name `fieldname`. The single file will be stored in `req.file`. #### `.array(fieldname[, maxCount])` Accept an array of files, all with the name `fieldname`. Optionally error out if more than `maxCount` files are uploaded. The array of files will be stored in `req.files`. Files skipped by `fileFilter` do not count towards `maxCount`. Use `limits.files` to bound how many files are read from a request. #### `.fields(fields)` Accept a mix of files, specified by `fields`. An object with arrays of files will be stored in `req.files`. `fields` should be an array of objects with `name` and optionally a `maxCount`. Example: ```javascript [ { name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 } ] ``` #### `.none()` Accept only text fields. If any file upload is made, error with code `LIMIT_UNEXPECTED_FILE` will be issued. #### `.any()` Accepts all files that come over the wire. An array of files will be stored in `req.files`. **WARNING:** Make sure that you always handle the files that a user uploads. Never add multer as a global middleware since a malicious user could upload files to a route that you didn't anticipate. Only use this function on routes where you are handling the uploaded files. ### `storage` #### `DiskStorage` The disk storage engine gives you full control on storing files to disk. ```javascript const crypto = require('crypto') const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, '/tmp/my-uploads') }, filename: function (req, file, cb) { crypto.randomBytes(16, function (err, raw) { if (err) return cb(err) cb(null, file.fieldname + '-' + raw.toString('hex')) }) } }) const upload = multer({ storage: storage }) ``` There are three options available: `destination`, `filename` and `flush`. All of them except `flush` are functions that determine where the file should be stored. `destination` is used to determine within which folder the uploaded files should be stored. This can also be given as a `string` (e.g. `'/tmp/uploads'`). If no `destination` is given, the operating system's default directory for temporary files is used. **Note:** You are responsible for creating the directory when providing `destination` as a function. When passing a string, multer will make sure that the directory is created for you. `filename` is used to determine what the file should be named inside the folder. If no `filename` is given, each file will be given a random name that doesn't include any file extension. **Note:** Multer will not append any file extension for you, your function should return a filename complete with a file extension. Each function gets passed both the request (`req`) and some information about the file (`file`) to aid with the decision. Note that `req.body` might not have been fully populated yet. It depends on the order that the client transmits fields and files to the server. For understanding the calling convention used in the callback (needing to pass null as the first param), refer to [Node.js error handling](https://web.archive.org/web/20220417042018/https://www.joyent.com/node-js/production/design/errors) `flush` is an optional boolean. When set to `true`, the file data is flushed to disk with an `fsync` call before the upload handler runs, which prevents data loss if the process or the system crashes while the data is still sitting in the operating system's page cache. It is disabled by default because forcing a disk flush on every upload has a performance cost. Note that this syncs the file contents only; if the new directory entry must survive a crash as well, fsync the destination directory yourself. #### `MemoryStorage` The memory storage engine stores the files in memory as `Buffer` objects. It doesn't have any options. ```javascript const storage = multer.memoryStorage() const upload = multer({ storage: storage }) ``` When using memory storage, the file info will contain a field called `buffer` that contains the entire file. **WARNING**: Uploading very large files, or relatively small files in large numbers very quickly, can cause your application to run out of memory when memory storage is used. ### `limits` An object specifying the size limits of the following optional properties. Multer passes this object into busboy directly, and the details of the properties can be found on [busboy's page](https://github.com/mscdex/busboy#exports). `limits` can also be a function that receives the request and returns such an object. It is called once per request, before parsing starts, so limits can depend on e.g. the authenticated user: ```javascript const upload = multer({ limits: function (req) { return { fileSize: req.user.maxUploadSize } } }) ``` Limits apply to the whole request; there is no per-file limit. To restrict individual files by type or name, use `fileFilter` or a custom storage engine. The following integer values are available: Key | Description | Default --- | --- | --- `fieldNameSize` | Max field name size | Infinity `fieldSize` | Max field value size (in bytes) | 1MB `fields` | Max number of non-file fields | Infinity `fileSize` | For multipart forms, the max file size (in bytes) | Infinity `files` | For multipart forms, the max number of file fields | Infinity `parts` | For multipart forms, the max number of parts (fields + files) | Infinity `headerPairs` | For multipart forms, the max number of header key=>value pairs to parse | 2000 `fieldNestingDepth` | Max number of nesting levels for field names (e.g. `a[b][c]` has 2 levels) | Infinity `fieldArrayIndexLimit` | Max numeric array index accepted inside a field name (e.g. `a[3]` uses index 3) | Infinity Specifying the limits can help protect your site against denial of service (DoS) attacks. ### `fileFilter` Set this to a function to control which files should be uploaded and which should be skipped. The function should look like this: ```javascript function fileFilter (req, file, cb) { // The function should call `cb` with a boolean // to indicate if the file should be accepted // To reject this file pass `false`, like so: cb(null, false) // To accept the file pass `true`, like so: cb(null, true) // You can always pass an error if something goes wrong: cb(new Error('I don\'t have a clue!')) } ``` ### `streamHandler` By default Multer reads the request with `req.pipe(busboy)`. Some platforms consume the request body before your handlers run, so there is nothing left to pipe. Google Cloud Functions and Firebase Functions, for example, expose the already-read body as `req.rawBody`. Provide a `streamHandler` to feed busboy yourself in that case: ```javascript const upload = multer({ storage: multer.memoryStorage(), streamHandler: function (req, busboy) { if (req.rawBody) { busboy.end(req.rawBody) } else { req.pipe(busboy) } } }) ``` The function receives the request and the busboy instance and must write the whole multipart body to busboy and end it. ## Security Specifying the [limits](#limits) can help protect your site against denial of service (DoS) attacks. The following limits are recommended for most applications: - `fileSize` -- set to the maximum expected file size for your use case - `files` -- set to the maximum number of files per request - `fields` -- set to the maximum number of text fields per request - `fieldNestingDepth` -- set to the minimum depth your field names require (e.g. `3` for `a[b][c]`) - `fieldArrayIndexLimit` -- set to the largest array index your field names require (e.g. `100` for `a[99]`) ## Error handling When encountering an error, Multer will delegate the error to Express. You can display a nice error page using [the standard express way](https://expressjs.com/en/guide/error-handling/). If you want to catch errors specifically from Multer, you can call the middleware function by yourself. Also, if you want to catch only [the Multer errors](https://github.com/expressjs/multer/blob/main/lib/multer-error.js), you can use the `MulterError` class that is attached to the `multer` object itself (e.g. `err instanceof multer.MulterError`). Multer errors carry a `code` (e.g. `LIMIT_FILE_SIZE`) and, when the error concerns a specific field, its name in `field`. Errors about a specific file (`LIMIT_FILE_SIZE`, `LIMIT_UNEXPECTED_FILE`) also expose the client-supplied file name in `filename`; treat it as untrusted input, like `file.originalname`. ```javascript const multer = require('multer') const upload = multer().single('avatar') app.post('/profile', function (req, res) { upload(req, res, function (err) { if (err instanceof multer.MulterError) { // A Multer error occurred when uploading. } else if (err) { // An unknown error occurred when uploading. } // Everything went fine. }) }) ``` ## Custom storage engine For information on how to build your own storage engine, see [Multer Storage Engine](https://github.com/expressjs/multer/blob/main/StorageEngine.md). ## License [MIT](LICENSE) [ci-image]: https://github.com/expressjs/multer/actions/workflows/ci.yml/badge.svg [ci-url]: https://github.com/expressjs/multer/actions/workflows/ci.yml [test-url]: https://coveralls.io/r/expressjs/multer?branch=main [test-image]: https://badgen.net/coveralls/c/github/expressjs/multer/main [npm-downloads-image]: https://badgen.net/npm/dm/multer [npm-url]: https://npmjs.org/package/multer [npm-version-image]: https://badgen.net/npm/v/multer [ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/multer/badge [ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/multer expressjs-multer-2c380d0/StorageEngine.md 0000664 0000000 0000000 00000006246 15266374662 0020500 0 ustar 00root root 0000000 0000000 # Multer Storage Engine Storage engines are classes that expose two functions: `_handleFile` and `_removeFile`. Follow the template below to get started with your own custom storage engine. When asking the user for input (such as where to save this file), always give them the parameters `req, file, cb`, in this order. This makes it easier for developers to switch between storage engines. For example, in the template below, the engine saves the files to the disk. The user tells the engine where to save the file, and this is done by providing the `destination` parameter: ```javascript var storage = myCustomStorage({ destination: function (req, file, cb) { cb(null, '/var/www/uploads/' + file.originalname) } }) ``` Your engine is responsible for storing the file and returning information on how to access the file in the future. This is done by the `_handleFile` function. The file data will be given to you as a stream (`file.stream`). You should pipe this data somewhere, and when you are done, call `cb` with some information on the file. A few rules about `file.stream`: - Always consume it. If you decide not to store the rest of a file, call `file.stream.resume()` to discard it and then call `cb`; parsing continues with the next part. Do not call `file.stream.destroy()`: busboy cannot continue after a destroyed part stream and the request would hang. - When the request is aborted or fails, `file.stream` emits `error` and `close`. Use `stream.pipeline(file.stream, yourStream, cb)` rather than `pipe()`, so your output stream is destroyed and `cb` is called with the error in that case. Multer then calls `_removeFile` for the files that were already stored, and for files still being written if `file.path` (or whatever `_removeFile` needs) has been set on the file object, so set it before you start writing. The information you provide in the callback will be merged with multer's file object, and then presented to the user via `req.files`. Your engine is also responsible for removing files if an error is encountered later on. Multer will decide which files to delete and when. Your storage class must implement the `_removeFile` function. It will receive the same arguments as `_handleFile`. Invoke the callback once the file has been removed. ## Template ```javascript var fs = require('fs') var pipeline = require('stream').pipeline function getDestination (req, file, cb) { cb(null, '/dev/null') } function MyCustomStorage (opts) { this.getDestination = (opts.destination || getDestination) } MyCustomStorage.prototype._handleFile = function _handleFile (req, file, cb) { this.getDestination(req, file, function (err, path) { if (err) return cb(err) var outStream = fs.createWriteStream(path) // Lets multer remove a partially written file if the request fails file.path = path pipeline(file.stream, outStream, function (err) { if (err) return cb(err) cb(null, { path: path, size: outStream.bytesWritten }) }) }) } MyCustomStorage.prototype._removeFile = function _removeFile (req, file, cb) { fs.unlink(file.path, cb) } module.exports = function (opts) { return new MyCustomStorage(opts) } ``` expressjs-multer-2c380d0/examples/ 0000775 0000000 0000000 00000000000 15266374662 0017232 5 ustar 00root root 0000000 0000000 expressjs-multer-2c380d0/examples/FormDataBlob/ 0000775 0000000 0000000 00000000000 15266374662 0021526 5 ustar 00root root 0000000 0000000 expressjs-multer-2c380d0/examples/FormDataBlob/.gitignore 0000664 0000000 0000000 00000000042 15266374662 0023512 0 ustar 00root root 0000000 0000000 node_modules public/data/uploads/ expressjs-multer-2c380d0/examples/FormDataBlob/README.md 0000664 0000000 0000000 00000000162 15266374662 0023004 0 ustar 00root root 0000000 0000000 ## FormDataBlob uses the `Blob` constructor to demonstrate sending a blob to the multer middleware on the server. expressjs-multer-2c380d0/examples/FormDataBlob/index.js 0000664 0000000 0000000 00000000573 15266374662 0023200 0 ustar 00root root 0000000 0000000 const express = require('express') const app = express() const multer = require('multer') const PORT = 3000 const upload = multer({ dest: './public/data/uploads/' }) app.use('/', express.static('public')) app.post('/upload', upload.single('uploaded_file'), (req, res) => { res.sendStatus(200) }) app.listen(PORT, () => console.log(`multer example listening on ${PORT}!`)) expressjs-multer-2c380d0/examples/FormDataBlob/package.json 0000664 0000000 0000000 00000000505 15266374662 0024014 0 ustar 00root root 0000000 0000000 { "name": "FormData", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node index.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^5.1.0", "multer": "^2.3.0" } } expressjs-multer-2c380d0/examples/FormDataBlob/public/ 0000775 0000000 0000000 00000000000 15266374662 0023004 5 ustar 00root root 0000000 0000000 expressjs-multer-2c380d0/examples/FormDataBlob/public/index.html 0000664 0000000 0000000 00000001755 15266374662 0025011 0 ustar 00root root 0000000 0000000