Skip to content

Commit

Permalink
* feat and fix: File size fix (#791)
Browse files Browse the repository at this point in the history
 * feat: maxFileSize option is now per file (as the name suggests)
 * feat: add maxFiles option, default Infinity
 * feat: add maxTotalFileSize, default is maxFileSize (for backwards compatibility)
 * fix: minFileSize is per file
 * fix: allowEmptyFiles fix in cases where one file is not empty
 * fix: allowEmptyFiles false option by default 
 * fix: rename wrongly named error
 * refactor: rename wrongly named maxFileSize into maxTotalFileSize
  • Loading branch information
GrosSacASac committed Dec 9, 2021
1 parent 27fdf69 commit 5cad764
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 26 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog


### 3.2.0


* feat: maxFileSize option is now per file (as the name suggests)
* feat: add maxFiles option, default Infinity
* feat: add maxTotalFileSize, default is maxFileSize (for backwards compatibility)
* fix: minFileSize is per file
* fix: allowEmptyFiles fix in cases where one file is not empty
* fix: allowEmptyFiles false option by default
* fix: rename wrongly named error
* refactor: rename wrongly named maxFileSize into maxTotalFileSize

### 3.1.5

* fix: PersistentFile.toString ([#796](https://github.com/node-formidable/formidable/pull/796))
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,12 @@ See it's defaults in [src/Formidable.js DEFAULT_OPTIONS](./src/Formidable.js)
files
- `options.minFileSize` **{number}** - default `1` (1byte); the minium size of
uploaded file.
- `options.maxFiles` **{number}** - default `Infinity`;
limit the amount of uploaded files.
- `options.maxFileSize` **{number}** - default `200 * 1024 * 1024` (200mb);
limit the size of uploaded file.
limit the size of each uploaded file.
- `options.maxTotalFileSize` **{number}** - default `options.maxFileSize`;
limit the size of the batch of uploaded files.
- `options.maxFields` **{number}** - default `1000`; limit the number of fields, set 0 for unlimited
- `options.maxFieldsSize` **{number}** - default `20 * 1024 * 1024` (20mb);
limit the amount of memory all fields together (except files) can allocate in
Expand Down
12 changes: 7 additions & 5 deletions examples/with-http.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const server = http.createServer((req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({
uploadDir: `uploads`,
// uploadDir: `uploads`,
keepExtensions: true,
// filename(/*name, ext, part, form*/) {
// /* name basename of the http originalFilename
Expand All @@ -24,10 +24,12 @@ const server = http.createServer((req, res) => {
// return 'yo.txt'; // or completly different name
// // return 'z/yo.txt'; // subdirectory
// },
filter: function ({name, originalFilename, mimetype}) {
// keep only images
return mimetype && mimetype.includes("image");
}
// filter: function ({name, originalFilename, mimetype}) {
// // keep only images
// return mimetype && mimetype.includes("image");
// }
// maxTotalFileSize: 4000,
// maxFileSize: 1000,

});

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "formidable",
"version": "3.1.5",
"version": "3.2.0",
"license": "MIT",
"description": "A node.js module for parsing form data, especially file uploads.",
"homepage": "https://github.com/node-formidable/formidable",
Expand All @@ -13,7 +13,7 @@
],
"publishConfig": {
"access": "public",
"tag": "v3"
"tag": "v4"
},
"scripts": {
"bench": "node benchmark",
Expand Down
71 changes: 54 additions & 17 deletions src/Formidable.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ const toHexoId = hexoid(25);
const DEFAULT_OPTIONS = {
maxFields: 1000,
maxFieldsSize: 20 * 1024 * 1024,
maxFiles: Infinity,
maxFileSize: 200 * 1024 * 1024,
maxTotalFileSize: undefined,
minFileSize: 1,
allowEmptyFiles: true,
allowEmptyFiles: false,
keepExtensions: false,
encoding: 'utf-8',
hashAlgorithm: false,
Expand All @@ -45,6 +47,9 @@ class IncomingForm extends EventEmitter {
super();

this.options = { ...DEFAULT_OPTIONS, ...options };
if (!this.options.maxTotalFileSize) {
this.options.maxTotalFileSize = this.options.maxFileSize
}

const dir = path.resolve(
this.options.uploadDir || this.options.uploaddir || os.tmpdir(),
Expand All @@ -69,7 +74,7 @@ class IncomingForm extends EventEmitter {

this._flushing = 0;
this._fieldsSize = 0;
this._fileSize = 0;
this._totalFileSize = 0;
this._plugins = [];
this.openedFiles = [];

Expand All @@ -89,6 +94,7 @@ class IncomingForm extends EventEmitter {
});

this._setUpMaxFields();
this._setUpMaxFiles();
this.ended = undefined;
this.type = undefined;
}
Expand Down Expand Up @@ -308,6 +314,7 @@ class IncomingForm extends EventEmitter {

this._flushing += 1;

let fileSize = 0;
const newFilename = this._getNewName(part);
const filepath = this._joinDirectoryName(newFilename);
const file = this._newFile({
Expand All @@ -325,22 +332,14 @@ class IncomingForm extends EventEmitter {
this.openedFiles.push(file);

part.on('data', (buffer) => {
this._fileSize += buffer.length;
if (this._fileSize < this.options.minFileSize) {
this._error(
new FormidableError(
`options.minFileSize (${this.options.minFileSize} bytes) inferior, received ${this._fileSize} bytes of file data`,
errors.smallerThanMinFileSize,
400,
),
);
return;
}
if (this._fileSize > this.options.maxFileSize) {
this._totalFileSize += buffer.length;
fileSize += buffer.length;

if (this._totalFileSize > this.options.maxTotalFileSize) {
this._error(
new FormidableError(
`options.maxFileSize (${this.options.maxFileSize} bytes) exceeded, received ${this._fileSize} bytes of file data`,
errors.biggerThanMaxFileSize,
`options.maxTotalFileSize (${this.options.maxTotalFileSize} bytes) exceeded, received ${this._totalFileSize} bytes of file data`,
errors.biggerThanTotalMaxFileSize,
413,
),
);
Expand All @@ -356,7 +355,7 @@ class IncomingForm extends EventEmitter {
});

part.on('end', () => {
if (!this.options.allowEmptyFiles && this._fileSize === 0) {
if (!this.options.allowEmptyFiles && fileSize === 0) {
this._error(
new FormidableError(
`options.allowEmptyFiles is false, file size should be greather than 0`,
Expand All @@ -366,6 +365,26 @@ class IncomingForm extends EventEmitter {
);
return;
}
if (fileSize < this.options.minFileSize) {
this._error(
new FormidableError(
`options.minFileSize (${this.options.minFileSize} bytes) inferior, received ${fileSize} bytes of file data`,
errors.smallerThanMinFileSize,
400,
),
);
return;
}
if (fileSize > this.options.maxFileSize) {
this._error(
new FormidableError(
`options.maxFileSize (${this.options.maxFileSize} bytes), received ${fileSize} bytes of file data`,
errors.biggerThanMaxFileSize,
413,
),
);
return;
}

file.end(() => {
this._flushing -= 1;
Expand Down Expand Up @@ -583,6 +602,24 @@ class IncomingForm extends EventEmitter {
}
}

_setUpMaxFiles() {
if (this.options.maxFiles !== Infinity) {
let fileCount = 0;
this.on('file', () => {
fileCount += 1;
if (fileCount > this.options.maxFiles) {
this._error(
new FormidableError(
`options.maxFiles (${this.options.maxFiles}) exceeded`,
errors.maxFilesExceeded,
413,
),
);
}
});
}
}

_maybeEnd() {
// console.log('ended', this.ended);
// console.log('_flushing', this._flushing);
Expand Down
6 changes: 5 additions & 1 deletion src/FormidableError.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ const filenameNotString = 1005;
const maxFieldsSizeExceeded = 1006;
const maxFieldsExceeded = 1007;
const smallerThanMinFileSize = 1008;
const biggerThanMaxFileSize = 1009;
const biggerThanTotalMaxFileSize = 1009;
const noEmptyFiles = 1010;
const missingContentType = 1011;
const malformedMultipart = 1012;
const missingMultipartBoundary = 1013;
const unknownTransferEncoding = 1014;
const maxFilesExceeded = 1015;
const biggerThanMaxFileSize = 1016;
const pluginFailed = 1017;

const FormidableError = class extends Error {
Expand All @@ -32,13 +34,15 @@ export {
filenameNotString,
maxFieldsSizeExceeded,
maxFieldsExceeded,
maxFilesExceeded,
smallerThanMinFileSize,
biggerThanMaxFileSize,
noEmptyFiles,
missingContentType,
malformedMultipart,
missingMultipartBoundary,
unknownTransferEncoding,
biggerThanTotalMaxFileSize,
pluginFailed,
};

Expand Down

0 comments on commit 5cad764

Please sign in to comment.