Skip to content

Commit cfcc465

Browse files
authored
Merge pull request #1 from felixge/master
Getting updates from upstream.
2 parents d93055d + 6041695 commit cfcc465

File tree

11 files changed

+77
-159
lines changed

11 files changed

+77
-159
lines changed

.travis.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
language: node_js
22
node_js:
3-
- 0.8
4-
- "0.10"
5-
- 0.11
3+
- 4
4+
- 6
5+
- 7

Readme.md

+22-124
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
# Formidable
22

3-
[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)
3+
[![Build Status](https://travis-ci.org/felixge/node-formidable.svg?branch=master)](https://travis-ci.org/felixge/node-formidable)
44

55
## Purpose
66

7-
A node.js module for parsing form data, especially file uploads.
7+
A Node.js module for parsing form data, especially file uploads.
88

99
## Current status
1010

11+
**Maintainers Wanted:** Please see https://github.com/felixge/node-formidable/issues/412
12+
1113
This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading
1214
and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from
1315
a large variety of clients and is considered production-ready.
@@ -22,19 +24,12 @@ a large variety of clients and is considered production-ready.
2224

2325
## Installation
2426

25-
This is a low level package, and if you're using a high level framework such as Express, chances are it's already included in it. You can [read this discussion](http://stackoverflow.com/questions/11295554/how-to-disable-express-bodyparser-for-file-uploads-node-js) about how Formidable is integrated with Express.
26-
27-
Via [npm](http://github.com/isaacs/npm):
28-
```
29-
npm install formidable@latest
30-
```
31-
Manually:
32-
```
33-
git clone git://github.com/felixge/node-formidable.git formidable
34-
vim my.js
35-
# var formidable = require('./formidable');
27+
```sh
28+
npm i -S formidable
3629
```
3730

31+
This is a low-level package, and if you're using a high-level framework it may already be included. However, [Express v4](http://expressjs.com) does not include any multipart handling, nor does [body-parser](https://github.com/expressjs/body-parser).
32+
3833
Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.
3934

4035
## Example
@@ -87,7 +82,7 @@ Sets encoding for incoming form fields.
8782
form.uploadDir = "/my/dir";
8883
```
8984
Sets the directory for placing file uploads in. You can move them later on using
90-
`fs.rename()`. The default is `os.tmpDir()`.
85+
`fs.rename()`. The default is `os.tmpdir()`.
9186

9287
```javascript
9388
form.keepExtensions = false;
@@ -272,7 +267,18 @@ Emitted when the entire request has been received, and all contained files have
272267

273268
## Changelog
274269

275-
### v1.0.14
270+
### v1.1.1 (2017-01-15)
271+
272+
* Fix DeprecationWarning about os.tmpDir() (Christian)
273+
* Update `buffer.write` order of arguments for Node 7 (Kornel Lesiński)
274+
* JSON Parser emits error events to the IncomingForm (alessio.montagnani)
275+
* Improved Content-Disposition parsing (Sebastien)
276+
* Access WriteStream of fs during runtime instead of include time (Jonas Amundsen)
277+
* Use built-in toString to convert buffer to hex (Charmander)
278+
* Add hash to json if present (Nick Stamas)
279+
* Add license to package.json (Simen Bekkhus)
280+
281+
### v1.0.14 (2013-05-03)
276282

277283
* Add failing hash tests. (Ben Trask)
278284
* Enable hash calculation again (Eugene Girshov)
@@ -304,120 +310,12 @@ Emitted when the entire request has been received, and all contained files have
304310
* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley)
305311
* Documentation improvements (Sven Lito, Andre Azevedo)
306312
* Add support for application/octet-stream (Ion Lupascu, Chris Scribner)
307-
* Use os.tmpDir() to get tmp directory (Andrew Kelley)
313+
* Use os.tmpdir() to get tmp directory (Andrew Kelley)
308314
* Improve package.json (Andrew Kelley, Sven Lito)
309315
* Fix benchmark script (Andrew Kelley)
310316
* Fix scope issue in incoming_forms (Sven Lito)
311317
* Fix file handle leak on error (OrangeDog)
312318

313-
### v1.0.11
314-
315-
* Calculate checksums for incoming files (sreuter)
316-
* Add definition parameters to "IncomingForm" as an argument (Math-)
317-
318-
### v1.0.10
319-
320-
* Make parts to be proper Streams (Matt Robenolt)
321-
322-
### v1.0.9
323-
324-
* Emit progress when content length header parsed (Tim Koschützki)
325-
* Fix Readme syntax due to GitHub changes (goob)
326-
* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)
327-
328-
### v1.0.8
329-
330-
* Strip potentially unsafe characters when using `keepExtensions: true`.
331-
* Switch to utest / urun for testing
332-
* Add travis build
333-
334-
### v1.0.7
335-
336-
* Remove file from package that was causing problems when installing on windows. (#102)
337-
* Fix typos in Readme (Jason Davies).
338-
339-
### v1.0.6
340-
341-
* Do not default to the default to the field name for file uploads where
342-
filename="".
343-
344-
### v1.0.5
345-
346-
* Support filename="" in multipart parts
347-
* Explain unexpected end() errors in parser better
348-
349-
**Note:** Starting with this version, formidable emits 'file' events for empty
350-
file input fields. Previously those were incorrectly emitted as regular file
351-
input fields with value = "".
352-
353-
### v1.0.4
354-
355-
* Detect a good default tmp directory regardless of platform. (#88)
356-
357-
### v1.0.3
358-
359-
* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)
360-
* Small performance improvements
361-
* New test suite and fixture system
362-
363-
### v1.0.2
364-
365-
* Exclude node\_modules folder from git
366-
* Implement new `'aborted'` event
367-
* Fix files in example folder to work with recent node versions
368-
* Make gently a devDependency
369-
370-
[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)
371-
372-
### v1.0.1
373-
374-
* Fix package.json to refer to proper main directory. (#68, Dean Landolt)
375-
376-
[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)
377-
378-
### v1.0.0
379-
380-
* Add support for multipart boundaries that are quoted strings. (Jeff Craig)
381-
382-
This marks the beginning of development on version 2.0 which will include
383-
several architectural improvements.
384-
385-
[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)
386-
387-
### v0.9.11
388-
389-
* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)
390-
* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class
391-
392-
**Important:** The old property names of the File class will be removed in a
393-
future release.
394-
395-
[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)
396-
397-
### Older releases
398-
399-
These releases were done before starting to maintain the above Changelog:
400-
401-
* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)
402-
* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)
403-
* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)
404-
* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)
405-
* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)
406-
* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)
407-
* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)
408-
* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)
409-
* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)
410-
* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)
411-
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
412-
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
413-
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
414-
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
415-
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
416-
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
417-
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
418-
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
419-
* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)
420-
421319
## License
422320

423321
Formidable is licensed under the MIT license.

benchmark/bench-multipart-parser.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ function createMultipartBuffer(boundary, size) {
5959
, tail = '\r\n--'+boundary+'--\r\n'
6060
, buffer = new Buffer(size);
6161

62-
buffer.write(head, 'ascii', 0);
63-
buffer.write(tail, 'ascii', buffer.length - tail.length);
62+
buffer.write(head, 0, 'ascii');
63+
buffer.write(tail, buffer.length - tail.length, 'ascii');
6464
return buffer;
6565
}
6666

example/post.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
require('../test/common');
1+
var common = require('../test/common');
22
var http = require('http'),
33
util = require('util'),
4-
formidable = require('formidable'),
4+
formidable = common.formidable,
5+
port = common.port,
56
server;
67

78
server = http.createServer(function(req, res) {
@@ -38,6 +39,6 @@ server = http.createServer(function(req, res) {
3839
res.end('404');
3940
}
4041
});
41-
server.listen(TEST_PORT);
42+
server.listen(port);
4243

43-
console.log('listening on http://localhost:'+TEST_PORT+'/');
44+
console.log('listening on http://localhost:'+port+'/');

example/upload.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
require('../test/common');
1+
var common = require('../test/common');
22
var http = require('http'),
33
util = require('util'),
4-
formidable = require('formidable'),
4+
os = require('os'),
5+
formidable = common.formidable,
6+
port = common.port,
57
server;
68

79
server = http.createServer(function(req, res) {
@@ -19,7 +21,7 @@ server = http.createServer(function(req, res) {
1921
files = [],
2022
fields = [];
2123

22-
form.uploadDir = TEST_TMP;
24+
form.uploadDir = os.tmpdir();
2325

2426
form
2527
.on('field', function(field, value) {
@@ -43,6 +45,6 @@ server = http.createServer(function(req, res) {
4345
res.end('404');
4446
}
4547
});
46-
server.listen(TEST_PORT);
48+
server.listen(port);
4749

48-
console.log('listening on http://localhost:'+TEST_PORT+'/');
50+
console.log('listening on http://localhost:'+port+'/');

lib/file.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
if (global.GENTLY) require = GENTLY.hijack(require);
22

33
var util = require('util'),
4-
WriteStream = require('fs').WriteStream,
4+
fs = require('fs'),
55
EventEmitter = require('events').EventEmitter,
66
crypto = require('crypto');
77

@@ -31,11 +31,11 @@ module.exports = File;
3131
util.inherits(File, EventEmitter);
3232

3333
File.prototype.open = function() {
34-
this._writeStream = new WriteStream(this.path);
34+
this._writeStream = new fs.WriteStream(this.path);
3535
};
3636

3737
File.prototype.toJSON = function() {
38-
return {
38+
var json = {
3939
size: this.size,
4040
path: this.path,
4141
name: this.name,
@@ -45,13 +45,22 @@ File.prototype.toJSON = function() {
4545
filename: this.filename,
4646
mime: this.mime
4747
};
48+
if (this.hash && this.hash != "") {
49+
json.hash = this.hash;
50+
}
51+
return json;
4852
};
4953

5054
File.prototype.write = function(buffer, cb) {
5155
var self = this;
5256
if (self.hash) {
5357
self.hash.update(buffer);
5458
}
59+
60+
if (this._writeStream.closed) {
61+
return cb();
62+
}
63+
5564
this._writeStream.write(buffer, function() {
5665
self.lastModifiedDate = new Date();
5766
self.size += buffer.length;

lib/incoming_form.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ function IncomingForm(opts) {
2525

2626
this.maxFields = opts.maxFields || 1000;
2727
this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024;
28+
this.maxFileSize = opts.maxFileSize || 2 * 1024 * 1024;
2829
this.keepExtensions = opts.keepExtensions || false;
29-
this.uploadDir = opts.uploadDir || os.tmpDir();
30+
this.uploadDir = opts.uploadDir || (os.tmpdir && os.tmpdir()) || os.tmpDir();
3031
this.encoding = opts.encoding || 'utf-8';
3132
this.headers = null;
3233
this.type = null;
@@ -39,6 +40,7 @@ function IncomingForm(opts) {
3940
this._parser = null;
4041
this._flushing = 0;
4142
this._fieldsSize = 0;
43+
this._fileSize = 0;
4244
this.openedFiles = [];
4345

4446
return this;
@@ -180,6 +182,7 @@ IncomingForm.prototype.onPart = function(part) {
180182
IncomingForm.prototype.handlePart = function(part) {
181183
var self = this;
182184

185+
// This MUST check exactly for undefined. You can not change it to !part.filename.
183186
if (part.filename === undefined) {
184187
var value = ''
185188
, decoder = new StringDecoder(this.encoding);
@@ -214,6 +217,11 @@ IncomingForm.prototype.handlePart = function(part) {
214217
this.openedFiles.push(file);
215218

216219
part.on('data', function(buffer) {
220+
self._fileSize += buffer.length;
221+
if (self._fileSize > self.maxFileSize) {
222+
self._error(new Error('maxFileSize exceeded, received '+self._fileSize+' bytes of file data'));
223+
return;
224+
}
217225
if (buffer.length == 0) {
218226
return;
219227
}
@@ -512,7 +520,7 @@ IncomingForm.prototype._initOctetStream = function() {
512520
IncomingForm.prototype._initJSONencoded = function() {
513521
this.type = 'json';
514522

515-
var parser = new JSONParser()
523+
var parser = new JSONParser(this)
516524
, self = this;
517525

518526
if (this.bytesExpected) {
@@ -532,11 +540,8 @@ IncomingForm.prototype._initJSONencoded = function() {
532540
};
533541

534542
IncomingForm.prototype._uploadPath = function(filename) {
535-
var name = 'upload_';
536543
var buf = crypto.randomBytes(16);
537-
for (var i = 0; i < buf.length; ++i) {
538-
name += ('0' + buf[i].toString(16)).slice(-2);
539-
}
544+
var name = 'upload_' + buf.toString('hex');
540545

541546
if (this.keepExtensions) {
542547
var ext = path.extname(filename);
@@ -555,4 +560,3 @@ IncomingForm.prototype._maybeEnd = function() {
555560

556561
this.emit('end');
557562
};
558-

lib/json_parser.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ if (global.GENTLY) require = GENTLY.hijack(require);
22

33
var Buffer = require('buffer').Buffer;
44

5-
function JSONParser() {
5+
function JSONParser(parent) {
6+
this.parent = parent;
67
this.data = new Buffer('');
78
this.bytesWritten = 0;
89
}
@@ -28,7 +29,9 @@ JSONParser.prototype.end = function() {
2829
for (var field in fields) {
2930
this.onField(field, fields[field]);
3031
}
31-
} catch (e) {}
32+
} catch (e) {
33+
this.parent.emit('error', e);
34+
}
3235
this.data = null;
3336

3437
this.onEnd();

0 commit comments

Comments
 (0)