From e081d486484bef2ef8b8ad36b13f2da70132acae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Louren=C3=A7o?= Date: Sat, 21 May 2022 23:32:42 +0100 Subject: [PATCH 01/20] fix(cve): bump busboy to fix CVE-2022-24434 --- lib/make-middleware.js | 22 +++++++--------------- package.json | 5 ++--- test/_util.js | 8 +------- test/error-handling.js | 2 +- test/express-integration.js | 3 +-- test/unicode.js | 36 +++++++++++++++++++++--------------- 6 files changed, 33 insertions(+), 43 deletions(-) diff --git a/lib/make-middleware.js b/lib/make-middleware.js index b033cbd9..6627cf4c 100644 --- a/lib/make-middleware.js +++ b/lib/make-middleware.js @@ -1,7 +1,6 @@ var is = require('type-is') var Busboy = require('busboy') var extend = require('xtend') -var onFinished = require('on-finished') var appendField = require('append-field') var Counter = require('./counter') @@ -9,10 +8,6 @@ var MulterError = require('./multer-error') var FileAppender = require('./file-appender') var removeUploadedFiles = require('./remove-uploaded-files') -function drainStream (stream) { - stream.on('readable', stream.read.bind(stream)) -} - function makeMiddleware (setup) { return function multerMiddleware (req, res, next) { if (!is(req, ['multipart'])) return next() @@ -30,7 +25,7 @@ function makeMiddleware (setup) { var busboy try { - busboy = new Busboy({ headers: req.headers, limits: limits, preservePath: preservePath }) + busboy = Busboy({ headers: req.headers, limits: limits, preservePath: preservePath }) } catch (err) { return next(err) } @@ -45,12 +40,9 @@ function makeMiddleware (setup) { function done (err) { if (isDone) return isDone = true - req.unpipe(busboy) - drainStream(req) busboy.removeAllListeners() - - onFinished(req, function () { next(err) }) + next(err) } function indicateDone () { @@ -80,9 +72,9 @@ function makeMiddleware (setup) { } // handle text field data - busboy.on('field', function (fieldname, value, fieldnameTruncated, valueTruncated) { + busboy.on('field', function (fieldname, value, { nameTruncated, valueTruncated }) { if (fieldname == null) return abortWithCode('MISSING_FIELD_NAME') - if (fieldnameTruncated) return abortWithCode('LIMIT_FIELD_KEY') + if (nameTruncated) return abortWithCode('LIMIT_FIELD_KEY') if (valueTruncated) return abortWithCode('LIMIT_FIELD_VALUE', fieldname) // Work around bug in Busboy (https://github.com/mscdex/busboy/issues/6) @@ -94,7 +86,7 @@ function makeMiddleware (setup) { }) // handle files - busboy.on('file', function (fieldname, fileStream, filename, encoding, mimetype) { + busboy.on('file', function (fieldname, fileStream, { filename, encoding, mimeType }) { // don't attach to the files object, if there is no file if (!filename) return fileStream.resume() @@ -107,7 +99,7 @@ function makeMiddleware (setup) { fieldname: fieldname, originalname: filename, encoding: encoding, - mimetype: mimetype + mimetype: mimeType } var placeholder = appender.insertPlaceholder(file) @@ -169,7 +161,7 @@ function makeMiddleware (setup) { busboy.on('partsLimit', function () { abortWithCode('LIMIT_PART_COUNT') }) busboy.on('filesLimit', function () { abortWithCode('LIMIT_FILE_COUNT') }) busboy.on('fieldsLimit', function () { abortWithCode('LIMIT_FIELD_COUNT') }) - busboy.on('finish', function () { + busboy.on('close', function () { readFinished = true indicateDone() }) diff --git a/package.json b/package.json index 6aec9996..70d535d9 100644 --- a/package.json +++ b/package.json @@ -20,11 +20,10 @@ ], "dependencies": { "append-field": "^1.0.0", - "busboy": "^0.2.11", + "busboy": "^1.0.0", "concat-stream": "^1.5.2", "mkdirp": "^0.5.4", "object-assign": "^4.1.1", - "on-finished": "^2.3.0", "type-is": "^1.6.4", "xtend": "^4.0.0" }, @@ -39,7 +38,7 @@ "testdata-w3c-json-form": "^1.0.0" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 6.0.0" }, "files": [ "LICENSE", diff --git a/test/_util.js b/test/_util.js index e62bdafc..a6782ad8 100644 --- a/test/_util.js +++ b/test/_util.js @@ -1,7 +1,6 @@ var fs = require('fs') var path = require('path') var stream = require('stream') -var onFinished = require('on-finished') exports.file = function file (name) { return fs.createReadStream(path.join(__dirname, 'files', name)) @@ -17,11 +16,6 @@ exports.submitForm = function submitForm (multer, form, cb) { var req = new stream.PassThrough() - req.complete = false - form.once('end', function () { - req.complete = true - }) - form.pipe(req) req.headers = { 'content-type': 'multipart/form-data; boundary=' + form.getBoundary(), @@ -29,7 +23,7 @@ exports.submitForm = function submitForm (multer, form, cb) { } multer(req, null, function (err) { - onFinished(req, function () { cb(err, req) }) + cb(err, req) }) }) } diff --git a/test/error-handling.js b/test/error-handling.js index b462e16e..6baad5ab 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -244,7 +244,7 @@ describe('Error Handling', function () { req.end(body) upload(req, null, function (err) { - assert.strictEqual(err.message, 'Unexpected end of multipart data') + assert.strictEqual(err.message, 'Unexpected end of form') done() }) }) diff --git a/test/express-integration.js b/test/express-integration.js index 87ab8869..0cda05d4 100644 --- a/test/express-integration.js +++ b/test/express-integration.js @@ -8,7 +8,6 @@ var util = require('./_util') var express = require('express') var FormData = require('form-data') var concat = require('concat-stream') -var onFinished = require('on-finished') var port = 34279 @@ -27,7 +26,7 @@ describe('Express Integration', function () { req.on('response', function (res) { res.on('error', cb) res.pipe(concat({ encoding: 'buffer' }, function (body) { - onFinished(req, function () { cb(null, res, body) }) + cb(null, res, body) })) }) } diff --git a/test/unicode.js b/test/unicode.js index b7f98214..851b0ebc 100644 --- a/test/unicode.js +++ b/test/unicode.js @@ -2,12 +2,10 @@ var assert = require('assert') -var path = require('path') -var util = require('./_util') var multer = require('../') var temp = require('fs-temp') var rimraf = require('rimraf') -var FormData = require('form-data') +var stream = require('stream') describe('Unicode', function () { var uploadDir, upload @@ -34,21 +32,29 @@ describe('Unicode', function () { }) it('should handle unicode filenames', function (done) { - var form = new FormData() - var parser = upload.single('small0') - var filename = '\ud83d\udca9.dat' - - form.append('small0', util.file('small0.dat'), { filename: filename }) - - util.submitForm(parser, form, function (err, req) { + var req = new stream.PassThrough() + var boundary = 'AaB03x' + var body = [ + '--' + boundary, + 'Content-Disposition: form-data; name="small0"; filename="poo.dat"; filename*=utf-8\'\'%F0%9F%92%A9.dat', + 'Content-Type: text/plain', + '', + 'test with unicode filename', + '--' + boundary + '--' + ].join('\r\n') + + req.headers = { + 'content-type': 'multipart/form-data; boundary=' + boundary, + 'content-length': body.length + } + + req.end(body) + + upload.single('small0')(req, null, function (err) { assert.ifError(err) - assert.strictEqual(path.basename(req.file.path), filename) - assert.strictEqual(req.file.originalname, filename) - + assert.strictEqual(req.file.originalname, '\ud83d\udca9.dat') assert.strictEqual(req.file.fieldname, 'small0') - assert.strictEqual(req.file.size, 1778) - assert.strictEqual(util.fileSize(req.file.path), 1778) done() }) From 63d28d00a5824a7b189571d08b87350a038e0b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Sun, 29 May 2022 09:22:03 +0200 Subject: [PATCH 02/20] history: 1.4.4-lts.1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9686cde2..6485e25b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 1.4.4-lts.1 + +- Bugfix: Bump busboy to fix CVE-2022-24434 (#1097) +- Breaking: Require Node.js 6.0.0 or later (#1097) + ## 1.4.4 - 2021-12-07 - Bugfix: Handle missing field names (#913) From 59c7ef3bc5080de3203f0a0d5243a18bcf11175e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Sun, 29 May 2022 09:22:36 +0200 Subject: [PATCH 03/20] version: 1.4.4-lts.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 70d535d9..625b487f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "multer", "description": "Middleware for handling `multipart/form-data`.", - "version": "1.4.4", + "version": "1.4.4-lts.1", "contributors": [ "Hage Yaapa (http://www.hacksparrow.com)", "Jaret Pfluger ", From bc5be94f109cbf1af03fc9521eac0c1f1b2ab988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Mon, 30 May 2022 17:32:29 +0200 Subject: [PATCH 04/20] history: 1.4.5-lts.1 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6485e25b..5aeb328f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 1.4.5-lts.1 + +- No changes ## 1.4.4-lts.1 - Bugfix: Bump busboy to fix CVE-2022-24434 (#1097) From ddb65bda47d4373e3e4552638935eb849662d0a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Mon, 30 May 2022 17:32:40 +0200 Subject: [PATCH 05/20] version: 1.4.5-lts.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 625b487f..8545a73d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "multer", "description": "Middleware for handling `multipart/form-data`.", - "version": "1.4.4-lts.1", + "version": "1.4.5-lts.1", "contributors": [ "Hage Yaapa (http://www.hacksparrow.com)", "Jaret Pfluger ", From f8f12ab8a6d5a821483d8ef375f3591902c566db Mon Sep 17 00:00:00 2001 From: Max Mathieu Date: Sat, 14 Jan 2023 05:45:14 -0500 Subject: [PATCH 06/20] Fix out-of-band error event from busboy --- lib/make-middleware.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/make-middleware.js b/lib/make-middleware.js index 6627cf4c..cc26414a 100644 --- a/lib/make-middleware.js +++ b/lib/make-middleware.js @@ -41,7 +41,9 @@ function makeMiddleware (setup) { if (isDone) return isDone = true req.unpipe(busboy) - busboy.removeAllListeners() + process.nextTick(() => { + busboy.removeAllListeners() + }) next(err) } From 44b7ab51b44688f6a8d1a7b071127fcd72874251 Mon Sep 17 00:00:00 2001 From: eleveS1 Date: Sat, 28 Jan 2023 12:39:29 +0100 Subject: [PATCH 07/20] Translated to french --- README.md | 21 +-- doc/README-fr.md | 334 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 345 insertions(+), 10 deletions(-) create mode 100644 doc/README-fr.md diff --git a/README.md b/README.md index 6feccd9c..ea9ccdb5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ 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`). -## Translations +## Translations This README is also available in other languages: @@ -16,6 +16,7 @@ This README is also available in other languages: - [Русский язык](https://github.com/expressjs/multer/blob/master/doc/README-ru.md) (Russian) - [Việt Nam](https://github.com/expressjs/multer/blob/master/doc/README-vi.md) (Vietnam) - [Português](https://github.com/expressjs/multer/blob/master/doc/README-pt-br.md) (Portuguese Brazil) +- [Français](https://github.com/expressjs/multer/blob/master/doc/README-fr.md) (French) ## Installation @@ -33,7 +34,7 @@ Don't forget the `enctype="multipart/form-data"` in your form. ```html
- +
``` @@ -83,11 +84,11 @@ Here's an example on how multer is used an HTML form. Take special note of the ` ```html
-
- - - -
+
+ + + +
``` @@ -97,9 +98,9 @@ Then in your javascript file you would add these lines to access both the file a 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) + // 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) }); ``` diff --git a/doc/README-fr.md b/doc/README-fr.md new file mode 100644 index 00000000..53fc9d4a --- /dev/null +++ b/doc/README-fr.md @@ -0,0 +1,334 @@ +# Multer [![Build Status](https://travis-ci.org/expressjs/multer.svg?branch=master)](https://travis-ci.org/expressjs/multer) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) + +Multer est un middleware node.js pour la gestion des données `multipart/form-data` qui est principalement utilisé pour télécharger des fichiers. +Il est écrit au-dessus de [busboy](https://github.com/mscdex/busboy) pour une efficacité maximale. + +**NOTE**: Multer ne traitera aucun formulaire qui ne soit pas un multipart (`multipart/form-data`). + +## Translations + +This README is also available in other languages: + +- [العربية](https://github.com/expressjs/multer/blob/master/doc/README-ar.md) (Arabe) +- [Español](https://github.com/expressjs/multer/blob/master/doc/README-es.md) (Espagnol) +- [简体中文](https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md) (Chinois) +- [한국어](https://github.com/expressjs/multer/blob/master/doc/README-ko.md) (Coréen) +- [Русский язык](https://github.com/expressjs/multer/blob/master/doc/README-ru.md) (Russe) +- [Việt Nam](https://github.com/expressjs/multer/blob/master/doc/README-vi.md) (Vietnamien) +- [Português](https://github.com/expressjs/multer/blob/master/doc/README-pt-br.md) (Portugais du Brésil) +- [Français](https://github.com/expressjs/multer/blob/master/doc/README-fr.md) (Français) + +## Installation + +```sh +$ npm install --save multer +``` + +## Usage + +Multer ajoute un objet `body` et un objet `file` ou `files` à l'objet `request`. L'objet `body` contient les valeurs des champs texte du formulaire, l'objet `file` ou `files` contient les fichiers téléchargés via le formulaire. + +Exemple d'utilisation de base : + +N'oubliez pas le `enctype="multipart/form-data"` dans votre formulaire. + +```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 est le fichier `avatar` + // req.body contiendra les champs de texte, s'il y en avait +}) + +app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) { + // req.files est un tableau de fichiers "photos" + // req.body contiendra les champs de texte, s'il y en avait +}) + +const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }]) +app.post('/cool-profile', cpUpload, function (req, res, next) { + // req.files est un objet (String -> Array) où fieldname est la clé et la valeur est un tableau de fichiers + // + // e.g. + // req.files['avatar'][0] -> Fichier + // req.files['gallery'] -> Tableau + // + // req.body contiendra les champs de texte, s'il y en avait +}) +``` + +Dans le cas où vous auriez besoin de gérer un formulaire en plusieurs parties texte uniquement, vous devez utiliser la méthode `.none()`: + +```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 contiens les champs de text +}) +``` + +Voici un exemple d'utilisation de multer dans un formulaire HTML. Faites particulièrement attention aux champs `enctype="multipart/form-data"` et `name="uploaded_file"`: + +```html +
+
+ + + +
+
+``` + +Ensuite, dans votre fichier javascript, vous ajouterez ces lignes pour accéder à la fois au fichier et au corps. Il est important que vous utilisiez la valeur du champ `name` du formulaire dans votre fonction de téléchargement. Cela indique à Multer dans quel champ de la requête il doit rechercher les fichiers. Si ces champs ne sont pas les mêmes dans le formulaire HTML et sur votre serveur, votre téléchargement échouera: +```javascript +const multer = require('multer') +const upload = multer({ dest: './public/data/uploads/' }) +app.post('/stats', upload.single('uploaded_file'), function (req, res) { + // req.file est le nom de votre fichier dans le formulaire ci-dessus, ici 'uploaded_file' + // req.body contiendra les champs de texte, s'il y en avait + console.log(req.file, req.body) +}); +``` + + + +## API + +### Informations sur les fichiers + +Chaque fichier contient les informations suivantes: + +Clé | Description | Notes +--- |------------------------------------------------| --- +`fieldname` | Nom du champ spécifié dans le formulaire | +`originalname` | Nom du fichier sur l'ordinateur de l'utilisateur | +`encoding` | Type d'encodage du fichier | +`mimetype` | Type Mime du fichier | +`size` | Taille du fichier en octets | +`destination` | TLe dossier dans lequel le fichier a été enregistré | `DiskStorage` +`filename` | Le nom du fichier dans la `destination` | `DiskStorage` +`path` | Le chemin d'accès complet au fichier téléchargé | `DiskStorage` +`buffer` | Un `Buffer` du fichier entier | `MemoryStorage` + +### `multer(opts)` + +Multer accepte un objet d'options, dont le plus basique est le `dest` +propriété, qui indique à Multer où télécharger les fichiers. Au cas où vous omettez l'objet +options, les fichiers seront conservés en mémoire et ne seront jamais écrits sur le disque. + +Par défaut, Multer renommera les fichiers afin d'éviter les conflits de nommage. Les +la fonction de renommage peut être personnalisée en fonction de vos besoins. + +Voici les options qui peuvent être transmises à Multer. + +Clé | Description +--- | --- +`dest` ou `storage` | Où stocker les fichiers +`fileFilter` | Fonction pour contrôler quels fichiers sont acceptés +`limits` | Limites des données téléchargées +`preservePath` | Conservez le chemin complet des fichiers au lieu du nom de base uniquement + +Dans une application Web moyenne, seul `dest` peut être requis et configuré comme indiqué dans +l'exemple suivant. + +```javascript +const upload = multer({ dest: 'uploads/' }) +``` + +Si vous voulez plus de contrôle sur vos téléchargements, vous voudrez utiliser le `storage` +option au lieu de `dest`. Multer est livré avec des moteurs de stockage `DiskStorage` +et `MemoryStorage`; D'autres moteurs sont disponibles auprès de tiers. + +#### `.single(fieldname)` + +Acceptez un seul fichier avec le nom `fieldname`. Le fichier unique sera stocké +dans `req.file`. + +#### `.array(fieldname[, maxCount])` + +Acceptez un tableau de fichiers, tous avec le nom `fieldname`. Eventuellement erreur si +plus de `maxCount` fichiers sont téléchargés. Le tableau de fichiers sera stocké dans +`req.files`. + +#### `.fields(fields)` + +Accepte un mélange de fichiers, spécifié par `fields`. Un objet avec des tableaux de fichiers +seront stockés dans `req.files`. + +`fields` doit être un tableau d'objets avec `name` et éventuellement un `maxCount`. +Exemple: + +```javascript +[ + { name: 'avatar', maxCount: 1 }, + { name: 'gallery', maxCount: 8 } +] +``` + +#### `.none()` + +N'acceptez que les champs de texte. Si un téléchargement de fichier est effectué, une erreur avec le code +"LIMIT\_UNEXPECTED\_FILE" sera émis. + +#### `.any()` + +Accepte tous les fichiers qui arrivent sur le fil. Un tableau de fichiers sera stocké dans +`req.files`. + +**ATTENTION:** Assurez-vous de toujours gérer les fichiers qu'un utilisateur télécharge. +N'ajoutez jamais multer en tant que middleware global car un utilisateur malveillant pourrait télécharger des +fichiers vers un itinéraire que vous n'aviez pas prévu. N'utilisez cette fonction que sur les itinéraires +où vous gérez les fichiers téléchargés. + +### `storage` + +#### `DiskStorage` + +Le moteur de stockage sur disque vous donne un contrôle total sur le stockage des fichiers sur le disque. + +```javascript +const storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, '/tmp/my-uploads') + }, + filename: function (req, file, cb) { + const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9) + cb(null, file.fieldname + '-' + uniqueSuffix) + } +}) + +const upload = multer({ storage: storage }) +``` + +Il y a deux options disponibles, `destination` et `filename`. Elles sont toutes les deux +des fonctions qui déterminent où le fichier doit être stocké. + +`destination` est utilisé pour déterminer dans quel dossier les fichiers téléchargés doivent +être stocké. Cela peut également être donné sous forme de `string` (par exemple `'/tmp/uploads'`). Sinon +`destination` est donné, le répertoire par défaut du système d'exploitation est utilisé pour les +fichiers temporaires. + +**Remarque:** Vous êtes responsable de la création du répertoire lorsque vous fournissez +`destination` en tant que fonction. Lors du passage d'une chaîne, multer s'assurera que +le répertoire est créé pour vous. + +`filename` est utilisé pour déterminer le nom du fichier dans le dossier. +Si aucun "nom de fichier" n'est donné, chaque fichier recevra un nom aléatoire qui n'inclut +pas d'extension de fichier. + +**Remarque:** Multer n'ajoutera aucune extension de fichier pour vous, votre fonction +doit renvoyer un nom de fichier complet avec une extension de fichier. + +Chaque fonction reçoit à la fois la requête (`req`) et des informations sur +le dossier (`file`) pour aider à la décision. + +Notez que `req.body` n'a peut-être pas encore été entièrement rempli. Cela dépend de l'ordre +où le client transmet les champs et les fichiers au serveur. + +Pour comprendre la convention d'appel utilisée dans le rappel (nécessité de passer +null comme premier paramètre), reportez-vous à +[Node.js error handling](https://web.archive.org/web/20220417042018/https://www.joyent.com/node-js/production/design/errors) + +#### `MemoryStorage` + +Le moteur de stockage en mémoire stocke les fichiers en mémoire en tant qu'objets `Buffer`. Il +n'a pas d'options. + +```javascript +const storage = multer.memoryStorage() +const upload = multer({ storage: storage }) +``` + +Lors de l'utilisation du stockage en mémoire, les informations sur le fichier contiendront un champ appelé +`buffer` qui contient le fichier entier. + +**ATTENTION**: Le téléchargement de fichiers très volumineux ou de fichiers relativement petits en grand +nombres très rapidement, peut entraîner un manque de mémoire de votre application lorsque +le stockage en mémoire est utilisé. + +### `limits` + +Un objet spécifiant les limites de taille des propriétés facultatives suivantes. Multer passe directement cet objet dans busboy, et les détails des propriétés peuvent être trouvés sur [la page de busboy](https://github.com/mscdex/busboy#busboy-methods). + +Les valeurs entières suivantes sont disponibles : + +Clé | Description | Default +--- |---------------------------------------------------------------------------| --- +`fieldNameSize` | Taille maximale du nom de champ | 100 bytes +`fieldSize` | Max field value size (in bytes) | 1MB +`fields` | Taille maximale de la valeur du champ (en octets) | Infinity +`fileSize` | Pour les formulaires multipart, la taille maximale du fichier (en octets) | Infinity +`files` | Pour les formulaires multipart, le nombre maximal de champs de fichier | Infinity +`parts` | Pour les formulaires multipart, le nombre max de parties (champs + fichiers) | Infinity +`headerPairs` | Pour les formulaires multipart, le nombre maximum de paires clé=>valeur d'en-tête à analyser | 2000 + +Spécifier les limites peut aider à protéger votre site contre les attaques par déni de service (DoS). + +### `fileFilter` + +Définissez ceci sur une fonction pour contrôler quels fichiers doivent être téléchargés et lesquels +devrait être ignoré. La fonction devrait ressembler à ceci: + +```javascript +function fileFilter (req, file, cb) { + + // La fonction doit appeler `cb` avec un booléen + // pour indiquer si le fichier doit être accepté + + // Pour rejeter ce fichier, passez `false`, comme ceci: + cb(null, false) + + // Pour accepter le fichier, passez `true`, comme ceci: + cb(null, true) + + // Vous pouvez toujours passer une erreur si quelque chose ne va pas: + cb(new Error('I don\'t have a clue!')) + +} +``` + +## Gestion des Erreurs + +En cas d'erreur, Multer déléguera l'erreur à Express. Vous pouvez +afficher une belle page d'erreur en utilisant [la voie express standard](http://expressjs.com/guide/error-handling.html). + +Si vous souhaitez détecter les erreurs spécifiquement de Multer, vous pouvez appeler la +fonction middleware par vous-même. Aussi, si vous voulez attraper seulement [les erreurs Multer](https://github.com/expressjs/multer/blob/master/lib/multer-error.js), vous pouvez utiliser la classe `MulterError` qui est jointe à l'objet `multer` lui-même (par exemple `err instanceof multer.MulterError`). + +```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) { + // Une erreur Multer s'est produite lors du téléchargement. + } else if (err) { + // Une erreur inconnue s'est produite lors du téléchargement. + } + + // Tout s'est bien passé. + }) +}) +``` + +## Moteur de stockage personnalisé + +Pour plus d'informations sur la création de votre propre moteur de stockage, consultez [Multer Storage Engine](https://github.com/expressjs/multer/blob/master/StorageEngine.md). + +## License + +[MIT](LICENSE) From 8cc3a5d548b50f4efa865534482cfe253d553f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Mon, 30 Jan 2023 16:21:11 +0700 Subject: [PATCH 08/20] Tweak indentation --- README.md | 12 ++++++------ doc/README-fr.md | 9 +++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index ea9ccdb5..8c4dc4d9 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Don't forget the `enctype="multipart/form-data"` in your form. ```html
- +
``` @@ -84,11 +84,11 @@ Here's an example on how multer is used an HTML form. Take special note of the ` ```html
-
- - - -
+
+ + + +
``` diff --git a/doc/README-fr.md b/doc/README-fr.md index 53fc9d4a..3f3f2150 100644 --- a/doc/README-fr.md +++ b/doc/README-fr.md @@ -97,14 +97,11 @@ Ensuite, dans votre fichier javascript, vous ajouterez ces lignes pour accéder const multer = require('multer') const upload = multer({ dest: './public/data/uploads/' }) app.post('/stats', upload.single('uploaded_file'), function (req, res) { - // req.file est le nom de votre fichier dans le formulaire ci-dessus, ici 'uploaded_file' - // req.body contiendra les champs de texte, s'il y en avait - console.log(req.file, req.body) + // req.file est le nom de votre fichier dans le formulaire ci-dessus, ici 'uploaded_file' + // req.body contiendra les champs de texte, s'il y en avait + console.log(req.file, req.body) }); ``` - - - ## API ### Informations sur les fichiers From cbb4a80b0d71ad3a29f8fa2db82a5fb9de0e0951 Mon Sep 17 00:00:00 2001 From: Vitor Ribeiro <72838474+vitorRibeiro7@users.noreply.github.com> Date: Tue, 25 Apr 2023 10:38:31 -0300 Subject: [PATCH 09/20] Update README-pt-br.md --- doc/README-pt-br.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/doc/README-pt-br.md b/doc/README-pt-br.md index 5fa2e7ee..d066ddd0 100644 --- a/doc/README-pt-br.md +++ b/doc/README-pt-br.md @@ -1,6 +1,6 @@ # Multer [![Build Status](https://travis-ci.org/expressjs/multer.svg?branch=master)](https://travis-ci.org/expressjs/multer) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) -Multer é um middleware node.js para manipulação `multipart/form-data`, que é usado principalmente para fazer upload de arquivos. Está escrito em cima do [busboy](https://github.com/mscdex/busboy) para máxima eficiência. +Multer é um middleware node.js para manipulação `multipart/form-data`, que é usado principalmente para fazer upload de arquivos. escrito em cima do [busboy](https://github.com/mscdex/busboy) para máxima eficiência. **NOTA**: Multer não processará nenhum formulário que não seja multipart (`multipart/form-data`). @@ -26,7 +26,7 @@ Multer adiciona um objeto `body` e um `file` ou objeto `files` para objeto `requ Exemplo de uso básico: -Não esqueça o `enctype="multipart/form-data"` em seu formulário. +Não esqueça o `enctype='multipart/form-data'` em seu formulário. ```html
@@ -36,30 +36,30 @@ Não esqueça o `enctype="multipart/form-data"` em seu formulário. ```javascript const express = require('express') -const multer = require('multer') +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 + // req.file é um arquivo `avatar` + // req.body conterá os campos de texto, se houver }) 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 + // req.files é um array de arquivos `photos` + // req.body conterá os campos de texto, se houver }) const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }]) app.post('/cool-profile', cpUpload, function (req, res, next) { - // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files + // req.files é um objeto (String -> Array) onde fieldname é a chave e o valor é array de arquivos // // e.g. - // req.files['avatar'][0] -> File + // req.files['avatar'][0] -> Arquivo // req.files['gallery'] -> Array // - // req.body will contain the text fields, if there were any + // req.body conterá os campos de texto, se houver }) ``` @@ -72,7 +72,7 @@ const multer = require('multer') const upload = multer() app.post('/profile', upload.none(), function (req, res, next) { - // req.body contains the text fields + // req.body contém os campos de texto }) ``` @@ -100,7 +100,7 @@ Multer aceita um objeto de opções, a propriedade mais básica é o `dest`, que Por padrão, Multer irá renomear os arquivos para evitar conflitos de nomes. A função de renomeação pode ser personalizada de acordo com suas necessidades. -A seguir estão as opções que podem ser passadas para Multer. +A seguir estão as opções que podem ser passadas para o Multer. Key | Descrição --- | --- @@ -123,7 +123,7 @@ Aceite um único arquivo com o nome `fieldname`. O arquivo único será armazena #### `.array(fieldname[, maxCount])` -Aceite múltiplos arquivos, todos com o nome `fieldname`. Opcional, gera um erro se mais de `maxCount` forem enviados. O array de arquivos serão armazenados em +Aceite múltiplos arquivos, todos com o nome `fieldname`. Opcional, gera um errose forem enviados mais de `maxCount`. O array de arquivos serão armazenados em `req.files`. #### `.fields(fields)` @@ -147,7 +147,7 @@ Aceite apenas campo de texto. Se algum upload de arquivo for feito, um erro com #### `.any()` -Aceita todos os arquivos que são enviaos. Uma matriz de arquivos será armazenada em +Aceita todos os arquivos que são enviados. Uma matriz de arquivos será armazenada em `req.files`. **AVISO:** Certifique-se de sempre manipular os arquivos que um usuário envia. @@ -226,7 +226,7 @@ A função deve ficar assim: function fileFilter (req, file, cb) { // A função deve chamar `cb` com um booleano - // to indicate if the file should be accepted + // para indicar se o arquivo deve ser aceito // Para rejeitar este arquivo passe `false`, assim: cb(null, false) @@ -253,12 +253,12 @@ 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. + // Ocorreu um erro Multer durante o upload. } else if (err) { - // An unknown error occurred when uploading. + // Ocorreu um erro Multer durante o upload. } - // Everything went fine. + // Tudo correu bem. }) }) ``` From 4da126f3fb9e3af76765013a3323d3c63a41e9dd Mon Sep 17 00:00:00 2001 From: Vitor Ribeiro <72838474+vitorRibeiro7@users.noreply.github.com> Date: Tue, 25 Apr 2023 10:40:23 -0300 Subject: [PATCH 10/20] Update README-pt-br.md --- doc/README-pt-br.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README-pt-br.md b/doc/README-pt-br.md index d066ddd0..ff0d18c5 100644 --- a/doc/README-pt-br.md +++ b/doc/README-pt-br.md @@ -1,6 +1,6 @@ # Multer [![Build Status](https://travis-ci.org/expressjs/multer.svg?branch=master)](https://travis-ci.org/expressjs/multer) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) -Multer é um middleware node.js para manipulação `multipart/form-data`, que é usado principalmente para fazer upload de arquivos. escrito em cima do [busboy](https://github.com/mscdex/busboy) para máxima eficiência. +Multer é um middleware node.js para manipulação `multipart/form-data`, que é usado principalmente para fazer upload de arquivos. Foi escrito em cima do [busboy](https://github.com/mscdex/busboy) para máxima eficiência. **NOTA**: Multer não processará nenhum formulário que não seja multipart (`multipart/form-data`). From 274550c2b366a26888bc4ca1c36fee76bfc51cfd Mon Sep 17 00:00:00 2001 From: Vitor Ribeiro <72838474+vitorRibeiro7@users.noreply.github.com> Date: Wed, 26 Apr 2023 07:51:46 -0300 Subject: [PATCH 11/20] Update README-pt-br.md --- doc/README-pt-br.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/README-pt-br.md b/doc/README-pt-br.md index ff0d18c5..e36a1f4f 100644 --- a/doc/README-pt-br.md +++ b/doc/README-pt-br.md @@ -253,9 +253,9 @@ const upload = multer().single('avatar') app.post('/profile', function (req, res) { upload(req, res, function (err) { if (err instanceof multer.MulterError) { - // Ocorreu um erro Multer durante o upload. + // Ocorreu um erro durante o upload. } else if (err) { - // Ocorreu um erro Multer durante o upload. + // Ocorreu um erro durante o upload. } // Tudo correu bem. From f1596eb8bb18ede3b1fe61582f496ddb6880115e Mon Sep 17 00:00:00 2001 From: Vitor Ribeiro <72838474+vitorRibeiro7@users.noreply.github.com> Date: Wed, 26 Apr 2023 12:09:20 -0300 Subject: [PATCH 12/20] Update README-pt-br.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Linus Unnebäck --- doc/README-pt-br.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README-pt-br.md b/doc/README-pt-br.md index e36a1f4f..ad3bebfb 100644 --- a/doc/README-pt-br.md +++ b/doc/README-pt-br.md @@ -56,7 +56,7 @@ app.post('/cool-profile', cpUpload, function (req, res, next) { // req.files é um objeto (String -> Array) onde fieldname é a chave e o valor é array de arquivos // // e.g. - // req.files['avatar'][0] -> Arquivo + // req.files['avatar'][0] -> File // req.files['gallery'] -> Array // // req.body conterá os campos de texto, se houver From 842088f54e010e94e6ff393515f5981522f83d1d Mon Sep 17 00:00:00 2001 From: Vitor Ribeiro <72838474+vitorRibeiro7@users.noreply.github.com> Date: Wed, 26 Apr 2023 12:09:33 -0300 Subject: [PATCH 13/20] Update README-pt-br.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Linus Unnebäck --- doc/README-pt-br.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README-pt-br.md b/doc/README-pt-br.md index ad3bebfb..996049b5 100644 --- a/doc/README-pt-br.md +++ b/doc/README-pt-br.md @@ -26,7 +26,7 @@ Multer adiciona um objeto `body` e um `file` ou objeto `files` para objeto `requ Exemplo de uso básico: -Não esqueça o `enctype='multipart/form-data'` em seu formulário. +Não esqueça o `enctype="multipart/form-data"` em seu formulário. ```html From 78a7535ce3cd535efd6aede28fecc552c5ccc3c9 Mon Sep 17 00:00:00 2001 From: eugene Date: Thu, 28 Sep 2023 16:19:40 +0500 Subject: [PATCH 14/20] doc: uzbek language --- doc/README-uz.md | 273 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 doc/README-uz.md diff --git a/doc/README-uz.md b/doc/README-uz.md new file mode 100644 index 00000000..80132fa7 --- /dev/null +++ b/doc/README-uz.md @@ -0,0 +1,273 @@ +# Multer [![Build Status](https://travis-ci.org/expressjs/multer.svg?branch=master)](https://travis-ci.org/expressjs/multer) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) + +Multer - bu nodejs middleware bo'lib, asosan `multipart/form-data` shaklda yuborilgan fayllarni yuklashda ishlatiladi. Yuqori samaradorlikka erishish uchun [busboy](https://github.com/mscdex/busboy)ning ustiga yozilgan. + +**Muhim**: Multer `multipart` bo'lmagan har qanday formani qayta ishlamaydi. + +## Tarjimalar + +Bu README boshqa tillarda ham mavjud: + +- [العربية](https://github.com/expressjs/multer/blob/master/doc/README-ar.md) (arabcha) +- [English](https://github.com/expressjs/multer/blob/master/README.md) (inglizcha) +- [Español](https://github.com/expressjs/multer/blob/master/doc/README-es.md) (ispancha) +- [简体中文](https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md) (xitoycha) +- [한국어](https://github.com/expressjs/multer/blob/master/doc/README-ko.md) (korescha) +- [Português](https://github.com/expressjs/multer/blob/master/doc/README-pt-br.md) (portugalcha) +- [Русский язык](https://github.com/expressjs/multer/blob/master/doc/README-ru.md) (ruscha) +- [Français](https://github.com/expressjs/multer/blob/master/doc/README-fr.md) (fransuzcha) + + +## O'rnatish + +```sh +$ npm install --save multer +``` + +## Foydalanish + +Multer - `request` ob'ektiga `body` va `file` yoki `files` ob'ektini qo'shadi. `body` ob'ekti formaning matn maydonlarining (fields) qiymatlarini o'z ichiga oladi, `file` yoki `files` ob'ekti forma orqali yuklangan fayllarni o'z ichiga oladi. + +Sodda ishlatish uchun namuna: + +Formada `enctype="multipart/form-data"` qo'shish esdan chiqmasin + +```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 - fayl `avatar` + // req.body agar matnli maydonlar (fields) bo'lsa, ularni saqlanadi +}) + +app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) { + // req.files - fayllar massivi `photos` + // req.body agar matnli maydonlar (fields) bo'lsa, ularni saqlanadi +}) + +const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }]) +app.post('/cool-profile', cpUpload, function (req, res, next) { + // req.files - bu ob'ekt (String -> Array), matn maydoni(fieldname) - bu key, va qiymat - fayllar massivi + // + // misol: + // req.files['avatar'][0] -> File + // req.files['gallery'] -> Array + // + // req.body agar matnli maydonlar (fields) bo'lsa, ularni saqlanadi +}) +``` + +Agarda siz faqat matndan iborat multipart form bilan ishlashingiz kerak bo'lsa, `.none()` ishlating: + +```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 matnli maydonlar (fields)ni o'zida saqlaydi +}) +``` + +## API + +### Fayl haqida ma'lumot + +Har bir fayl quyidagi ma'lumotlarni o'zida saqlaydi: + +Kalit(key) | Ta'rif | Eslatma +--- |----------------------------------------| --- +`fieldname` | Formada berilgan maxsus nom | +`originalname` | Foydalanuvchi kompyuteridagi fayl nomi | +`encoding` | Faylning kodlash turi | +`mimetype` | Faylning `mime` turi | +`size` | Fayl hajmi - baytda | +`destination` | Fayl saqlangan papka | `DiskStorage` +`filename` | `destination`ni ichidagi fayl nomi | `DiskStorage` +`path` | Yuklangan faylning to'liq yo'li | `DiskStorage` +`buffer` | Butun boshli fayl `Buffer` tipda | `MemoryStorage` + +### `multer(opts)` + +Multer qo'shimcha ob'ekt qabul qiladi, ulardan eng asosiysi - `dest`, +Multerga fayllarni qayerga yuklash kerakligini aytadigan xususiyat. Agarda siz qo'shimcha(`options`) ob'ektni tashlab ketsangiz, fayllar xotirada saqlanadi va hech qachon diskka yozilmaydi. + +Standart holatda - Multer nomlashda kelib chiqishi mumkin bo'lgan muammolarni oldini olish uchun fayllar nomini o'zgartiradi. O'z talablaringizga mos ravishda nomlash funksiyasini sozlay olashingiz mumkin. + +Quyidagilar Multerga qo'shimcha qiymat sifati berilishi mumkin: + +Kalit(key) | Ta'rif +--- | --- +`dest` yoki `storage` | Faylni qayerda saqlash +`fileFilter` | Qaysi fayllar qabul qilinishini boshqarish funksiyasi +`limits` | Yuklash chegarasi +`preservePath` | Asosiy nom o'rniga fayllarning to'liq yo'lini saqlash + +O'rtacha veb-ilovada faqat `dest` kerak bo'lishi mumkin va quyidagicha sozlanishi mumkin + +```javascript +const upload = multer({ dest: 'uploads/' }) +``` +Yuklamalaringizni boshqarishda ko'proq nazoratni xohlasangiz, `dest` o'rniga `storage` tanlovini ishlatishingiz kerak. Multer `DiskStorage` va `MemoryStorage` saqlash motorlari(engines) bilan keladi. Boshqa motorlar(engines) uchun uchinchi tomondan(third parties) ko'proq tanlovlar keladi. + +#### `.single(fieldname)` + +`fieldname` nomi bilan yagona faylni qabul qiladi. Yagona fayl `req.file` da saqlanadi. + +#### `.array(fieldname[, maxCount])` + +`fieldname` nomi bilan fayllar massivini qabul qiladi. Agar `maxCount` dan ko'p fayl yuklash urinishi bo'lsa, hatolikni aniqlash imkoniyatini berish mumkin. Fayllar massivi `req.files` da saqlanadi. + +#### `.fields(fields)` + +`fields`da aniqlangan fayllarni qabul qiladi. Fayllar massivini saqlash uchun `req.files` ichidagi massivda saqlanadi. + +`fields` ob'ektida `name` va `maxCount` kalitlar(keys)ni o'z ichiga olishi kerak. Misol: + +```javascript +[ + { name: 'avatar', maxCount: 1 }, + { name: 'gallery', maxCount: 8 } +] +``` + +#### `.none()` + +Faqatgina matnli maydonlar(fields)ni oladi. Agarda biror fayl yuklansa, "LIMIT\_UNEXPECTED\_FILE" xatoligi yuboriladi. + +#### `.any()` + +Ushbu so'rov barcha fayllarni qabul qiladi, fayllar `req.files` ichida saqlanadi. + +**OGOHLANTIRISH:** Foydalanuvchi yuklagan fayllarni doimo boshqarib turishni unutmang. Ularni boshqa yo'l(route)ni kutmagan holda fayllarini yuklash imkonini beradigan global middleware sifatida multerni sozlamang. Faqatgina yuklangan fayllarni boshqarish kerak bo'lgan yo'l(route)larda ushbu funksiyani ishlating. + +### `storage` + +#### `DiskStorage` + +Diskka saqlash motori(engine) sizga fayllarni saqlashda to'liq nazorat qilish imkonini beradi. + +```javascript +const storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, '/tmp/my-uploads') + }, + filename: function (req, file, cb) { + cb(null, file.fieldname + '-' + Date.now()) + } +}) + +const upload = multer({ storage: storage }) +``` + +`destination` va `filename` qo'shimcha tanlovlari mavjud, ular ikkala ham qaysi papkada faylni saqlash kerakligini aniqlab turadigan funksiyalardir. + +`destination` yuklangan fayllarni qaysi papkada saqlash kerakligini aniqlab turadi. Bu, `string` sifatida berilishi mumkin (masalan, `'/tmp/uploads'`). Agar `destination` berilmagan bo'lsa, operatsion tizimning vaqtinchalik fayllar uchun ishlatiladigan papkasini ishlatadi. + +**Diqqat:** `destination` ni funksiya sifatida berib bo'lganda papka ochilganligiga o'zingiz javobgar bo'lasiz. Agar `string` sifatida bersangiz, multer papkani o'zi uchun yaratishni ta'minlaydi. + +`filename` faylni papka ichida qanday nomlanganligini aniqlaydi. Agar `filename` berilmagan bo'lsa, har bir faylga fayl kengaytmasini o'z ichiga olmagan tasodifiy nom beriladi. + +**Diqqat:** Multer siz uchun fayl kengaytmasini qo'shmaydi, sizning funksiyangiz kengaytma bilan to'liq nomni qaytarishi kerak. + +Har bir funksiya `req` so'rovini va fayl haqida ma'lumotlarni (`file`) olish uchun o'tkaziladi. + +Diqqat qiling, `req.body` hali to'liq to'ldirilmagan bo'lishi mumkin. Bu mijozning maydon(field)larni va fayllarni serverga qanday yuborishiga bog'liq bo'ladi. + +Callback funktsiyasida ishlatiladigan chaqirish tartibini tushunish uchun (birinchi parametr sifatida null o‘tkazish talab etilishi) ko‘rish uchun quyidagi manzilga murojaat qiling: +[Node.js da xatoliklarni ushlash](https://web.archive.org/web/20220417042018/https://www.joyent.com/node-js/production/design/errors) + +#### `MemoryStorage` + +Xotira saqlash motori fayllarni xotirada `Buffer` ob'ektlar sifatida saqlaydi. Uning qo'shimcha qiymatlari yo‘q. + +```javascript +const storage = multer.memoryStorage() +const upload = multer({ storage: storage }) +``` +Xotirada saqlash paytida, fayl ma'lumotlari `buffer` deb nomlanadigan maydonni o‘z ichiga oladi. + +**DIQQAT:** Juda katta fayllarni yuklash, yoki kichik fayllarni tez-tez yuklash, xotirada saqlash ishlatilganda, sizning ilovangizning xotirasini to'ldirib qo'yishi mumkin. + +### `limits` + +Quyidagi xususiyatlar o'lchov(limit)larni aniqlaydigan obyekt. Multer ushbu obyektni to'g'ridan-to'g'ri busboy ga o'tkazadi va xususiyatlar tafsilotlari [busboy sahifasida](https://github.com/mscdex/busboy#busboy-methods)dan topishingiz mumkin. + +Quyidagi butun qiymatlar mavjud: + +Kalit(key) | Ta'rif | Odatiy qiymat +--- |---------------------------------------------------------------------------------------------| --- +`fieldNameSize` | Maksimal maydon nomi o'lchami | 100 bayt +`fieldSize` | Maksimal maydon qiymati o'lchami (baytlarda) | 1MB +`fields` | Fayl bo'lmagan maydonlarning maksimal soni | Cheklanmagan +`fileSize` | Multipart form uchun faylning maksimal o'lchami (baytda) | Cheklanmagan +`files` | Multipart form uchun fayllar sonining maksimal chegarasi | Cheklanmagan +`parts` | Multipart form uchun fayllar sonining maksimal chegarasi (fieldlar va fayllar) | Cheklanmagan +`headerPairs` | Multipart form uchun ma'lumotlar (kalit va qiymat juftliklari) sonining maksimal chegarasi | 2000 + +Chegaralarni sozlash, DoS-hujumlariga qarshi saytingizni himoya qilishga yordam bera olishi mumkin + +### `fileFilter` + +Bu, qaysi fayllarni yuklashi, qaysilarini o'tkazib yuborish kerakligini boshqarish uchun funksiya sifatida sozlasa bo'ladi. Funksiya quyidagi ko'rinishda bo'lishi kerak:" + +```javascript +function fileFilter (req, file, cb) { + + // Bu funksiya, faylni qabul qilish kerakligini anglatish uchun `cb` ni + // boolean qiymat bilan chaqirish kerak. + + // Faylni qabul qilishni rad etish uchun false quyudagicha berilishi kerak: + cb(null, false) + + // Faylni qabul qiilishni tasdiqlash uchun true quyudagicha berilishi kerak: + cb(null, true) + + // Nimadir xato ketsa, siz har doim Error berishingiz mumkin: + cb(new Error('I don\'t have a clue!')) + +} +``` + +## Xatolar bilan ishlash + +Xatoga duch kelganda, Multer xatoni Expressga yuboradi. [standart express usuli](http://expressjs.com/guide/error-handling.html)dan foydalanib xatoni tartibliroq chiqarishingiz mumkin. + +Agar siz Multerdan chiqqan xatolarni aniqlamoqchi bo'lsangiz o'zingiz `middleware` funksiya yozishingiz mumkin. Shuningdek, agar siz faqat [Multer xatolarini](https://github.com/expressjs/multer/blob/master/lib/multer-error.js) ushlamoqchi bo'lsangiz, siz `multer` ob'ektiga yozilgan `MulterError` class ni ishlatishingiz mumkin (masalan, `err instanceof multer.MulterError`). + + +```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) { + // Yuklanishda Multerdan xatolik yuz berganda. + } else { + // Yuklanishda noma'lum xatolik yuz berganda. + } + + // Hammasi muvaffaqqiyatli bo'lganda. + }) +}) +``` + +## Maxsus saqlash mexanizmi + +O'zingizning saqlash dvigatelingizni qanday yaratish haqida ma'lumot olish: [Maxsus saqlash mexanizmi](https://github.com/expressjs/multer/blob/master/StorageEngine.md). + +## Litsenziya + +[MIT](LICENSE) From 2c01eb61d51e93cd9128e3398c451906c23278f6 Mon Sep 17 00:00:00 2001 From: eugene Date: Fri, 29 Sep 2023 08:18:45 +0500 Subject: [PATCH 15/20] doc: uzb lang added --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8c4dc4d9..f84d265f 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ This README is also available in other languages: - [Việt Nam](https://github.com/expressjs/multer/blob/master/doc/README-vi.md) (Vietnam) - [Português](https://github.com/expressjs/multer/blob/master/doc/README-pt-br.md) (Portuguese Brazil) - [Français](https://github.com/expressjs/multer/blob/master/doc/README-fr.md) (French) +- [Uzbek](https://github.com/expressjs/multer/blob/master/doc/README-uz.md) (Uzbek) ## Installation From be3d4de267147065a8d66f3c4a9e4a2aef1b4207 Mon Sep 17 00:00:00 2001 From: eugene Date: Fri, 29 Sep 2023 08:20:19 +0500 Subject: [PATCH 16/20] doc: fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f84d265f..fc5702a3 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ This README is also available in other languages: - [Việt Nam](https://github.com/expressjs/multer/blob/master/doc/README-vi.md) (Vietnam) - [Português](https://github.com/expressjs/multer/blob/master/doc/README-pt-br.md) (Portuguese Brazil) - [Français](https://github.com/expressjs/multer/blob/master/doc/README-fr.md) (French) -- [Uzbek](https://github.com/expressjs/multer/blob/master/doc/README-uz.md) (Uzbek) +- [O'zbek tili](https://github.com/expressjs/multer/blob/master/doc/README-uz.md) (Uzbek) ## Installation From 2a4ff0392e4e6b6867130de6ba2bf0fbda6df7d1 Mon Sep 17 00:00:00 2001 From: Igor Caldeira Andrade <122459409+Igor-CA@users.noreply.github.com> Date: Sat, 13 Apr 2024 10:16:19 -0300 Subject: [PATCH 17/20] docs: replace link (#1251) - PR-URL: https://github.com/expressjs/multer/pull/1251 - Fix a issue with pt-br readme - English link was linking to russian documentation --- doc/README-pt-br.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README-pt-br.md b/doc/README-pt-br.md index 996049b5..baf45033 100644 --- a/doc/README-pt-br.md +++ b/doc/README-pt-br.md @@ -8,7 +8,7 @@ Multer é um middleware node.js para manipulação `multipart/form-data`, que é Este README também está disponível em outros idiomas: -- [English](https://github.com/expressjs/multer/blob/master/doc/README-ru.md) (Inglês) +- [English](https://github.com/expressjs/multer/blob/master/README.md) (Inglês) - [Español](https://github.com/expressjs/multer/blob/master/doc/README-es.md) (Espanhol) - [简体中文](https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md) (Chinês) - [한국어](https://github.com/expressjs/multer/blob/master/doc/README-ko.md) (Coreano) From 67409df7ea0e9c95e2acf000b47bd25f4b2f459a Mon Sep 17 00:00:00 2001 From: Carlos Stenzel Date: Mon, 15 Apr 2024 07:26:34 -0300 Subject: [PATCH 18/20] docs: update texts in pt-br and remove duplicated references in ko (#1252) PR-URL: https://github.com/expressjs/multer/pull/1252 --- doc/README-ko.md | 1 - doc/README-pt-br.md | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/doc/README-ko.md b/doc/README-ko.md index 897ba529..90ef53a8 100644 --- a/doc/README-ko.md +++ b/doc/README-ko.md @@ -9,7 +9,6 @@ Multer는 파일 업로드를 위해 사용되는 `multipart/form-data` 를 다 이 문서는 아래의 언어로도 제공됩니다: - [العربية](https://github.com/expressjs/multer/blob/master/doc/README-ar.md) (아라비아 말) -- [English](https://github.com/expressjs/multer/blob/master/README.md) - [English](https://github.com/expressjs/multer/blob/master/README.md) (영어) - [Español](https://github.com/expressjs/multer/blob/master/doc/README-es.md) (스페인어) - [简体中文](https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md) (중국어) diff --git a/doc/README-pt-br.md b/doc/README-pt-br.md index baf45033..f97306c1 100644 --- a/doc/README-pt-br.md +++ b/doc/README-pt-br.md @@ -9,10 +9,15 @@ Multer é um middleware node.js para manipulação `multipart/form-data`, que é Este README também está disponível em outros idiomas: - [English](https://github.com/expressjs/multer/blob/master/README.md) (Inglês) +- [العربية](https://github.com/expressjs/multer/blob/master/doc/README-ar.md) (Árabe) - [Español](https://github.com/expressjs/multer/blob/master/doc/README-es.md) (Espanhol) - [简体中文](https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md) (Chinês) - [한국어](https://github.com/expressjs/multer/blob/master/doc/README-ko.md) (Coreano) - [Русский язык](https://github.com/expressjs/multer/blob/master/doc/README-ru.md) (Russo) +- [Việt Nam](https://github.com/expressjs/multer/blob/master/doc/README-vi.md) (Vietnã) +- [Português](https://github.com/expressjs/multer/blob/master/doc/README-pt-br.md) (Português Brasil) +- [Français](https://github.com/expressjs/multer/blob/master/doc/README-fr.md) (Francês) +- [O'zbek tili](https://github.com/expressjs/multer/blob/master/doc/README-uz.md) (Uzbequistão) ## Instalação @@ -76,6 +81,30 @@ app.post('/profile', upload.none(), function (req, res, next) { }) ``` +Aqui está um exemplo de como o multer é usado em um formulário HTML. Onde adicionamos `enctype="multipart/form-data"` no form e no input `name="uploaded_file"`: + +```html +
+
+ + + +
+
+``` + +Então, em seu arquivo javascript, você adicionaria essas linhas para acessar o arquivo e o corpo. É importante que você use o valor do campo `name` do formulário em sua função de upload. Isso informa ao multer em qual campo da solicitação ele deve procurar os arquivos. Se esses campos não forem iguais no formulário HTML e no seu servidor, seu upload falhará: + +```javascript +const multer = require('multer') +const upload = multer({ dest: './public/data/uploads/' }) +app.post('/stats', upload.single('uploaded_file'), function (req, res) { + // req.fileé o nome do seu arquivo no formato acima, aqui 'uploaded_file' + // req.body irá conter os campos de texto, se houver algum + console.log(req.file, req.body) +}); +``` + ## API ### Informação de arquivo @@ -187,6 +216,10 @@ Cada função é passada pelo request (`req`) e algumas informações sobre o ar Observe que `req.body` pode não ter sido totalmente preenchido ainda. Isso depende da ordem na qual o cliente transmite campos e arquivos para o servidor. +Para entender a convenção de chamada usada no callback (precisando passar +null como o primeiro parâmetro), consulte em +[Manipulação de erros no Node.js](https://web.archive.org/web/20220417042018/https://www.joyent.com/node-js/production/design/errors) + #### `MemoryStorage` O mecanismo de armazenamento na memória, armazena os arquivos na memória como um objeto `Buffer`. Não tendo opções. From cd4cd41f6e6668621c36b970c3eaffcfe08bccbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Marqu=C3=ADnez=20Prado?= <25435858+inigomarquinez@users.noreply.github.com> Date: Tue, 14 May 2024 18:19:47 +0200 Subject: [PATCH 19/20] ci: add support for OSSF scorecard reporting (#1260) PR-URL: https://github.com/expressjs/multer/pull/1260 --- .github/workflows/scorecard.yml | 73 +++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000..0e064f47 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,73 @@ +# 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: [ "master" ] + +# 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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.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@2f93e4319b2f04a2efc38fa7f78bd681bc3f7b2f # v2.23.2 + with: + sarif_file: results.sarif From c28306189a5ded5ff0c9b8044060d5cd4a2f1090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Marqu=C3=ADnez=20Prado?= <25435858+inigomarquinez@users.noreply.github.com> Date: Thu, 13 Jun 2024 19:17:16 +0200 Subject: [PATCH 20/20] ci: replace travis with github action (#1259) * ci: replace travis with github action * docs: replace travis badge by github action badge * chore: update dependencies and scripts * ci: add code coverage * ci: remove unused supertest * chore: update mkdirp as the version used was deprecated * ci: remove node 0.8 * chore: comment node v5, v7, v9 * chore: comment node v5, v7, v9 * chore: comment node v5, v7, v9 * chore: remove comments * test: add exit option to mocha and separate lint command * ci: include node 5,7 and 9 again * ci: revert include node 5,7 and 9 again * ci: remove node v5,7 and 9 * Update package.json Co-authored-by: Chris de Almeida * Delete package-lock.json --------- Co-authored-by: Chris de Almeida --- .github/workflows/ci.yml | 187 +++++++++++++++++++++++++++++++++++++++ .travis.yml | 9 -- README.md | 2 +- package.json | 10 ++- 4 files changed, 195 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..d4f5cae7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,187 @@ +name: ci + +on: +- pull_request +- push + +jobs: + test: + runs-on: ubuntu-20.04 + strategy: + matrix: + name: + - Node.js 0.10 + - Node.js 0.12 + - io.js 1.x + - io.js 2.x + - io.js 3.x + - Node.js 4.x + - Node.js 6.x + - Node.js 8.x + - 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 + + include: + - name: Node.js 0.10 + node-version: "0.10" + npm-i: mocha@3.5.3 nyc@10.3.2 + + - name: Node.js 0.12 + node-version: "0.12" + npm-i: mocha@3.5.3 nyc@10.3.2 + + - name: io.js 1.x + node-version: "1.8" + npm-i: mocha@3.5.3 nyc@10.3.2 + + - name: io.js 2.x + node-version: "2.5" + npm-i: mocha@3.5.3 nyc@10.3.2 + + - name: io.js 3.x + node-version: "3.3" + npm-i: mocha@3.5.3 nyc@10.3.2 + + - name: Node.js 4.x + node-version: "4.9" + npm-i: mocha@5.2.0 nyc@11.9.0 + + - name: Node.js 6.x + node-version: "6.17" + npm-i: mocha@6.2.2 nyc@14.1.1 + + - name: Node.js 8.x + node-version: "8.17" + npm-i: mocha@7.1.2 nyc@14.1.1 + + - name: Node.js 10.x + node-version: "10.24" + 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.22" + 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.21" + + - name: Node.js 15.x + node-version: "15.14" + + - name: Node.js 16.x + node-version: "16.20" + + - name: Node.js 17.x + node-version: "17.9" + + - name: Node.js 18.x + node-version: "18.18" + + - name: Node.js 19.x + node-version: "19.9" + + - name: Node.js 20.x + node-version: "20.9" + + - name: Node.js 21.x + node-version: "21.1" + + - name: Node.js 22.x + node-version: "22.0" + + steps: + - uses: actions/checkout@v4 + + - name: Install Node.js ${{ matrix.node-version }} + shell: bash -eo pipefail -l {0} + run: | + nvm install --default ${{ matrix.node-version }} + if [[ "${{ matrix.node-version }}" == 0.* && "$(cut -d. -f2 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then + nvm install --alias=npm 0.10 + nvm use ${{ matrix.node-version }} + if [[ "$(npm -v)" == 1.1.* ]]; then + nvm exec npm npm install -g npm@1.1 + ln -fs "$(which npm)" "$(dirname "$(nvm which npm)")/npm" + else + sed -i '1s;^.*$;'"$(printf '#!%q' "$(nvm which npm)")"';' "$(readlink -f "$(which npm)")" + fi + npm config set strict-ssl false + fi + dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" + + - name: Configure npm + run: | + if [[ "$(npm config get package-lock)" == "true" ]]; then + npm config set package-lock false + else + npm config set shrinkwrap false + fi + + - 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 + id: list_env + shell: bash + run: | + echo "node@$(node -v)" + echo "npm@$(npm -v)" + npm -s ls ||: + (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT" + + - name: Lint code + run: npm run lint + + - name: Run tests + shell: bash + run: | + if npm -ps ls nyc | grep -q nyc; then + npm run test-ci + else + npm test + fi + + - name: Collect code coverage + uses: coverallsapp/github-action@master + if: steps.list_env.outputs.nyc != '' + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: run-${{ matrix.test_number }} + parallel: true + + coverage: + needs: test + runs-on: ubuntu-latest + steps: + - name: Upload code coverage + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 343dd5a1..00000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -sudo: false -language: node_js -node_js: - - "0.10" - - "0.12" - - "4" - - "6" - - "8" - - "10" diff --git a/README.md b/README.md index fc5702a3..677bc937 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Multer [![Build Status](https://travis-ci.org/expressjs/multer.svg?branch=master)](https://travis-ci.org/expressjs/multer) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) +# Multer [![Build Status](https://badgen.net/github/checks/expressjs/multer/master?label=ci)](https://github.com/expressjs/multer/actions/workflows/ci.yml) [![Test Coverage](https://badgen.net/coveralls/c/github/expressjs/multer/master)](https://coveralls.io/r/expressjs/multer?branch=master) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) 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. diff --git a/package.json b/package.json index 6aec9996..fa669581 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "append-field": "^1.0.0", "busboy": "^0.2.11", "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", + "mkdirp": "^0.5.6", "object-assign": "^4.1.1", "on-finished": "^2.3.0", "type-is": "^1.6.4", @@ -33,7 +33,8 @@ "express": "^4.13.1", "form-data": "^1.0.0-rc1", "fs-temp": "^1.1.2", - "mocha": "^3.5.3", + "mocha": "^10.4.0", + "nyc": "^15.1.0", "rimraf": "^2.4.1", "standard": "^14.3.3", "testdata-w3c-json-form": "^1.0.0" @@ -48,6 +49,9 @@ "lib/" ], "scripts": { - "test": "standard && mocha" + "lint": "standard", + "test": "standard && mocha --reporter spec --bail --exit --check-leaks test/", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" } }