formstream 1.3.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +49 -33
- package/lib/formstream.js +132 -31
- package/package.json +6 -3
- package/types/formstream.d.ts +8 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2012 - 2014 fengmk2 <fengmk2@gmail.com>
|
|
4
|
+
Copyright (c) 2014-present node-modules and other contributors.
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# formstream
|
|
2
2
|
|
|
3
3
|
[![NPM version][npm-image]][npm-url]
|
|
4
|
-
[](https://github.com/node-modules/formstream/actions/workflows/ci.yml)
|
|
5
|
+
[![Test coverage][codecov-image]][codecov-url]
|
|
5
6
|
[![npm download][download-image]][download-url]
|
|
6
7
|
|
|
7
8
|
[npm-image]: https://img.shields.io/npm/v/formstream.svg?style=flat-square
|
|
8
9
|
[npm-url]: https://npmjs.org/package/formstream
|
|
9
|
-
[
|
|
10
|
-
[
|
|
10
|
+
[codecov-image]: https://codecov.io/github/node-modules/formstream/coverage.svg?branch=master
|
|
11
|
+
[codecov-url]: https://codecov.io/github/node-modules/formstream?branch=master
|
|
11
12
|
[download-image]: https://img.shields.io/npm/dm/formstream.svg?style=flat-square
|
|
12
13
|
[download-url]: https://npmjs.org/package/formstream
|
|
13
14
|
|
|
@@ -16,7 +17,7 @@ A [multipart/form-data](http://tools.ietf.org/html/rfc2388) encoded stream, help
|
|
|
16
17
|
## Install
|
|
17
18
|
|
|
18
19
|
```bash
|
|
19
|
-
|
|
20
|
+
npm install formstream
|
|
20
21
|
```
|
|
21
22
|
|
|
22
23
|
## Quick Start
|
|
@@ -61,19 +62,44 @@ var formstream = require('formstream');
|
|
|
61
62
|
|
|
62
63
|
var filepath = './logo.png';
|
|
63
64
|
fs.stat(filepath, function (err, stat) {
|
|
64
|
-
formstream()
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
formstream()
|
|
66
|
+
.field('status', 'share picture')
|
|
67
|
+
.field('access_token', 'your access token')
|
|
68
|
+
.file('pic', filepath, 'logo.png', stat.size)
|
|
69
|
+
.pipe(process.stdout); // your request stream
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Set min chunk buffer size
|
|
74
|
+
|
|
75
|
+
Some web servers have a limit on the number of chunks, and you can set `minChunkSize` to ensure the size of chunk sent to the server.
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
var fs = require('fs');
|
|
79
|
+
var FormStream = require('formstream');
|
|
80
|
+
|
|
81
|
+
var filepath = './big-file.zip';
|
|
82
|
+
fs.stat(filepath, function (err, stat) {
|
|
83
|
+
new FormStream({
|
|
84
|
+
// send >= 2MB chunk buffer size to the server
|
|
85
|
+
minChunkSize: 1024 * 1024 * 2,
|
|
86
|
+
}).field('status', 'share file')
|
|
87
|
+
.field('access_token', 'your access token')
|
|
88
|
+
.file('file', filepath, 'big-file.zip', stat.size)
|
|
89
|
+
.pipe(process.stdout); // your request stream
|
|
68
90
|
});
|
|
69
91
|
```
|
|
70
92
|
|
|
71
93
|
## API Doc
|
|
72
94
|
|
|
73
|
-
### formstream()
|
|
95
|
+
### formstream([options])
|
|
74
96
|
|
|
75
97
|
Create a form instance.
|
|
76
98
|
|
|
99
|
+
#### Arguments
|
|
100
|
+
|
|
101
|
+
- **options.minChunkSize** Number - min chunk size to emit data event
|
|
102
|
+
|
|
77
103
|
#### Returns
|
|
78
104
|
|
|
79
105
|
Form - form instance
|
|
@@ -143,7 +169,7 @@ Get headers for the request.
|
|
|
143
169
|
|
|
144
170
|
#### Arguments
|
|
145
171
|
|
|
146
|
-
-
|
|
172
|
+
- **headers** Object - Additional headers
|
|
147
173
|
|
|
148
174
|
#### Example
|
|
149
175
|
|
|
@@ -176,26 +202,16 @@ See [Node.js Documentation](http://nodejs.org/api/stream.html#stream_event_end)
|
|
|
176
202
|
|
|
177
203
|
## License
|
|
178
204
|
|
|
179
|
-
(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
The above copyright notice and this permission notice shall be
|
|
193
|
-
included in all copies or substantial portions of the Software.
|
|
194
|
-
|
|
195
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
196
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
197
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
198
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
199
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
200
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
201
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
205
|
+
[MIT](LICENSE)
|
|
206
|
+
|
|
207
|
+
<!-- GITCONTRIBUTOR_START -->
|
|
208
|
+
|
|
209
|
+
## Contributors
|
|
210
|
+
|
|
211
|
+
|[<img src="https://avatars.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars.githubusercontent.com/u/288288?v=4" width="100px;"/><br/><sub><b>xingrz</b></sub>](https://github.com/xingrz)<br/>|[<img src="https://avatars.githubusercontent.com/u/32174276?v=4" width="100px;"/><br/><sub><b>semantic-release-bot</b></sub>](https://github.com/semantic-release-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/13151189?v=4" width="100px;"/><br/><sub><b>fjc0k</b></sub>](https://github.com/fjc0k)<br/>|[<img src="https://avatars.githubusercontent.com/u/18096247?v=4" width="100px;"/><br/><sub><b>mrspeiser</b></sub>](https://github.com/mrspeiser)<br/>|[<img src="https://avatars.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|
|
|
212
|
+
| :---: | :---: | :---: | :---: | :---: | :---: |
|
|
213
|
+
[<img src="https://avatars.githubusercontent.com/u/7326406?v=4" width="100px;"/><br/><sub><b>shaozj</b></sub>](https://github.com/shaozj)<br/>
|
|
214
|
+
|
|
215
|
+
This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Wed May 15 2024 00:34:12 GMT+0800`.
|
|
216
|
+
|
|
217
|
+
<!-- GITCONTRIBUTOR_END -->
|
package/lib/formstream.js
CHANGED
|
@@ -1,28 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Data format:
|
|
2
|
+
* Form Data format:
|
|
3
3
|
*
|
|
4
4
|
|
|
5
|
+
```txt
|
|
5
6
|
--FormStreamBoundary1349886663601\r\n
|
|
6
7
|
Content-Disposition: form-data; name="foo"\r\n
|
|
7
8
|
\r\n
|
|
8
9
|
<FIELD-CONTENT>\r\n
|
|
9
10
|
--FormStreamBoundary1349886663601\r\n
|
|
11
|
+
Content-Disposition: form-data; name="data"\r\n
|
|
12
|
+
Content-Type: application/json\r\n
|
|
13
|
+
\r\n
|
|
14
|
+
<JSON-FORMAT-CONTENT>\r\n
|
|
15
|
+
--FormStreamBoundary1349886663601\r\n
|
|
10
16
|
Content-Disposition: form-data; name="file"; filename="formstream.test.js"\r\n
|
|
11
17
|
Content-Type: application/javascript\r\n
|
|
12
18
|
\r\n
|
|
13
|
-
<FILE-CONTENT
|
|
19
|
+
<FILE-CONTENT-CHUNK-1>
|
|
20
|
+
...
|
|
21
|
+
<FILE-CONTENT-CHUNK-N>
|
|
22
|
+
\r\n
|
|
14
23
|
--FormStreamBoundary1349886663601\r\n
|
|
15
24
|
Content-Disposition: form-data; name="pic"; filename="fawave.png"\r\n
|
|
16
25
|
Content-Type: image/png\r\n
|
|
17
26
|
\r\n
|
|
18
27
|
<IMAGE-CONTENT>\r\n
|
|
19
28
|
--FormStreamBoundary1349886663601--
|
|
29
|
+
```
|
|
20
30
|
|
|
21
31
|
*
|
|
22
32
|
*/
|
|
23
33
|
|
|
24
34
|
'use strict';
|
|
25
35
|
|
|
36
|
+
var debug = require('util').debuglog('formstream');
|
|
26
37
|
var Stream = require('stream');
|
|
27
38
|
var parseStream = require('pause-stream');
|
|
28
39
|
var util = require('util');
|
|
@@ -30,14 +41,15 @@ var mime = require('mime');
|
|
|
30
41
|
var path = require('path');
|
|
31
42
|
var fs = require('fs');
|
|
32
43
|
var destroy = require('destroy');
|
|
44
|
+
var hex = require('node-hex');
|
|
33
45
|
|
|
34
46
|
var PADDING = '--';
|
|
35
47
|
var NEW_LINE = '\r\n';
|
|
36
48
|
var NEW_LINE_BUFFER = Buffer.from(NEW_LINE);
|
|
37
49
|
|
|
38
|
-
function FormStream() {
|
|
50
|
+
function FormStream(options) {
|
|
39
51
|
if (!(this instanceof FormStream)) {
|
|
40
|
-
return new FormStream();
|
|
52
|
+
return new FormStream(options);
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
FormStream.super_.call(this);
|
|
@@ -49,6 +61,10 @@ function FormStream() {
|
|
|
49
61
|
this._contentLength = 0;
|
|
50
62
|
this._isAllStreamSizeKnown = true;
|
|
51
63
|
this._knownStreamSize = 0;
|
|
64
|
+
this._minChunkSize = options && options.minChunkSize || 0;
|
|
65
|
+
|
|
66
|
+
this.isFormStream = true;
|
|
67
|
+
debug('start boundary\n%s', this._boundary);
|
|
52
68
|
}
|
|
53
69
|
|
|
54
70
|
util.inherits(FormStream, Stream);
|
|
@@ -76,12 +92,12 @@ FormStream.prototype.setTotalStreamSize = function (size) {
|
|
|
76
92
|
|
|
77
93
|
for (var i = 0; i < this._streams.length; i++) {
|
|
78
94
|
size += this._streams[i][0].length;
|
|
79
|
-
size += NEW_LINE_BUFFER.length; // stream field end
|
|
95
|
+
size += NEW_LINE_BUFFER.length; // stream field end padding size
|
|
80
96
|
}
|
|
81
97
|
|
|
82
98
|
this._knownStreamSize = size;
|
|
83
99
|
this._isAllStreamSizeKnown = true;
|
|
84
|
-
|
|
100
|
+
debug('set total size: %s', size);
|
|
85
101
|
return this;
|
|
86
102
|
};
|
|
87
103
|
|
|
@@ -92,7 +108,6 @@ FormStream.prototype.headers = function (options) {
|
|
|
92
108
|
|
|
93
109
|
// calculate total stream size
|
|
94
110
|
this._contentLength += this._knownStreamSize;
|
|
95
|
-
|
|
96
111
|
// calculate length of end padding
|
|
97
112
|
this._contentLength += this._endData.length;
|
|
98
113
|
|
|
@@ -106,19 +121,20 @@ FormStream.prototype.headers = function (options) {
|
|
|
106
121
|
}
|
|
107
122
|
}
|
|
108
123
|
|
|
124
|
+
debug('headers: %j', headers);
|
|
109
125
|
return headers;
|
|
110
126
|
};
|
|
111
127
|
|
|
112
128
|
FormStream.prototype.file = function (name, filepath, filename, filesize) {
|
|
113
|
-
var mimeType = mime.getType(filepath);
|
|
114
|
-
|
|
115
129
|
if (typeof filename === 'number' && !filesize) {
|
|
116
130
|
filesize = filename;
|
|
117
131
|
filename = path.basename(filepath);
|
|
118
|
-
}
|
|
132
|
+
}
|
|
133
|
+
if (!filename) {
|
|
119
134
|
filename = path.basename(filepath);
|
|
120
135
|
}
|
|
121
136
|
|
|
137
|
+
var mimeType = mime.getType(filename);
|
|
122
138
|
var stream = fs.createReadStream(filepath);
|
|
123
139
|
|
|
124
140
|
return this.stream(name, stream, filename, mimeType, filesize);
|
|
@@ -128,9 +144,10 @@ FormStream.prototype.file = function (name, filepath, filename, filesize) {
|
|
|
128
144
|
* Add a form field
|
|
129
145
|
* @param {String} name field name
|
|
130
146
|
* @param {String|Buffer} value field value
|
|
147
|
+
* @param {String} [mimeType] field mimeType
|
|
131
148
|
* @return {this}
|
|
132
149
|
*/
|
|
133
|
-
FormStream.prototype.field = function (name, value) {
|
|
150
|
+
FormStream.prototype.field = function (name, value, mimeType) {
|
|
134
151
|
if (!Buffer.isBuffer(value)) {
|
|
135
152
|
// field(String, Number)
|
|
136
153
|
// https://github.com/qiniu/nodejs-sdk/issues/123
|
|
@@ -139,7 +156,7 @@ FormStream.prototype.field = function (name, value) {
|
|
|
139
156
|
}
|
|
140
157
|
value = Buffer.from(value);
|
|
141
158
|
}
|
|
142
|
-
return this.buffer(name, value);
|
|
159
|
+
return this.buffer(name, value, null, mimeType);
|
|
143
160
|
};
|
|
144
161
|
|
|
145
162
|
FormStream.prototype.stream = function (name, stream, filename, mimeType, size) {
|
|
@@ -190,38 +207,37 @@ FormStream.prototype.buffer = function (name, buffer, filename, mimeType) {
|
|
|
190
207
|
|
|
191
208
|
var leading = this._leading(disposition, mimeType);
|
|
192
209
|
|
|
193
|
-
this._buffers.push([leading, buffer]);
|
|
194
|
-
|
|
195
210
|
// plus buffer length to total content-length
|
|
196
|
-
|
|
197
|
-
this.
|
|
198
|
-
this._contentLength +=
|
|
211
|
+
var bufferSize = leading.length + buffer.length + NEW_LINE_BUFFER.length;
|
|
212
|
+
this._buffers.push(Buffer.concat([leading, buffer, NEW_LINE_BUFFER], bufferSize));
|
|
213
|
+
this._contentLength += bufferSize;
|
|
199
214
|
|
|
200
215
|
process.nextTick(this.resume.bind(this));
|
|
201
|
-
|
|
216
|
+
if (debug.enabled) {
|
|
217
|
+
debug('new buffer field, content size: %d\n%s%s',
|
|
218
|
+
buffer.length, leading.toString(), hex(buffer));
|
|
219
|
+
}
|
|
202
220
|
return this;
|
|
203
221
|
};
|
|
204
222
|
|
|
205
223
|
FormStream.prototype._leading = function (disposition, type) {
|
|
206
224
|
var leading = [PADDING + this._boundary];
|
|
207
225
|
|
|
208
|
-
var
|
|
226
|
+
var dispositions = [];
|
|
209
227
|
|
|
210
228
|
if (disposition) {
|
|
211
229
|
for (var k in disposition) {
|
|
212
|
-
|
|
230
|
+
dispositions.push(k + '="' + disposition[k] + '"');
|
|
213
231
|
}
|
|
214
232
|
}
|
|
215
233
|
|
|
216
|
-
leading.push('Content-Disposition: form-data; ' +
|
|
217
|
-
|
|
234
|
+
leading.push('Content-Disposition: form-data; ' + dispositions.join('; '));
|
|
218
235
|
if (type) {
|
|
219
236
|
leading.push('Content-Type: ' + type);
|
|
220
237
|
}
|
|
221
238
|
|
|
222
239
|
leading.push('');
|
|
223
240
|
leading.push('');
|
|
224
|
-
|
|
225
241
|
return Buffer.from(leading.join(NEW_LINE));
|
|
226
242
|
};
|
|
227
243
|
|
|
@@ -231,26 +247,101 @@ FormStream.prototype._emitBuffers = function () {
|
|
|
231
247
|
}
|
|
232
248
|
|
|
233
249
|
for (var i = 0; i < this._buffers.length; i++) {
|
|
234
|
-
|
|
235
|
-
this.emit('data', item[0]); // part leading
|
|
236
|
-
this.emit('data', item[1]); // part content
|
|
237
|
-
this.emit('data', NEW_LINE_BUFFER);
|
|
250
|
+
this.emit('data', this._buffers[i]);
|
|
238
251
|
}
|
|
239
|
-
|
|
240
252
|
this._buffers = [];
|
|
241
253
|
};
|
|
242
254
|
|
|
243
255
|
FormStream.prototype._emitStream = function (item) {
|
|
244
256
|
var self = this;
|
|
245
|
-
// item: [
|
|
246
|
-
|
|
257
|
+
// item: [ leading, stream ]
|
|
258
|
+
var streamSize = 0;
|
|
259
|
+
var chunkCount = 0;
|
|
260
|
+
const leading = item[0];
|
|
261
|
+
self.emit('data', leading);
|
|
262
|
+
chunkCount++;
|
|
263
|
+
if (debug.enabled) {
|
|
264
|
+
debug('new stream, chunk index %d\n%s', chunkCount, leading.toString());
|
|
265
|
+
}
|
|
247
266
|
|
|
248
267
|
var stream = item[1];
|
|
249
268
|
stream.on('data', function (data) {
|
|
250
269
|
self.emit('data', data);
|
|
270
|
+
streamSize += leading.length;
|
|
271
|
+
chunkCount++;
|
|
272
|
+
if (debug.enabled) {
|
|
273
|
+
if (data.length > 512) {
|
|
274
|
+
debug('stream chunk, size %d, chunk index %d, stream size %d\n%s...... only show 512 bytes ......',
|
|
275
|
+
data.length, chunkCount, streamSize, hex(data.slice(0, 512)));
|
|
276
|
+
} else {
|
|
277
|
+
debug('stream chunk, size %d, chunk index %d, stream size %d\n%s',
|
|
278
|
+
data.length, chunkCount, streamSize, hex(data));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
251
281
|
});
|
|
252
282
|
stream.on('end', function () {
|
|
253
283
|
self.emit('data', NEW_LINE_BUFFER);
|
|
284
|
+
chunkCount++;
|
|
285
|
+
debug('stream end, chunk index %d, stream size %d', chunkCount, streamSize);
|
|
286
|
+
return process.nextTick(self.drain.bind(self));
|
|
287
|
+
});
|
|
288
|
+
stream.resume();
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
FormStream.prototype._emitStreamWithChunkSize = function (item, minChunkSize) {
|
|
292
|
+
var self = this;
|
|
293
|
+
// item: [ leading, stream ]
|
|
294
|
+
var streamSize = 0;
|
|
295
|
+
var chunkCount = 0;
|
|
296
|
+
var bufferSize = 0;
|
|
297
|
+
var buffers = [];
|
|
298
|
+
const leading = item[0];
|
|
299
|
+
buffers.push(leading);
|
|
300
|
+
bufferSize += leading.length;
|
|
301
|
+
if (debug.enabled) {
|
|
302
|
+
debug('new stream, with min chunk size: %d\n%s', minChunkSize, leading.toString());
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
var stream = item[1];
|
|
306
|
+
stream.on('data', function (data) {
|
|
307
|
+
if (typeof data === 'string') {
|
|
308
|
+
data = Buffer.from(data, 'utf-8');
|
|
309
|
+
}
|
|
310
|
+
buffers.push(data);
|
|
311
|
+
bufferSize += data.length;
|
|
312
|
+
streamSize += data.length;
|
|
313
|
+
debug('got stream data size %d, buffer size %d, stream size %d',
|
|
314
|
+
data.length, bufferSize, streamSize);
|
|
315
|
+
if (bufferSize >= minChunkSize) {
|
|
316
|
+
const chunk = Buffer.concat(buffers, bufferSize);
|
|
317
|
+
buffers = [];
|
|
318
|
+
bufferSize = 0;
|
|
319
|
+
self.emit('data', chunk);
|
|
320
|
+
chunkCount++;
|
|
321
|
+
if (debug.enabled) {
|
|
322
|
+
if (chunk.length > 512) {
|
|
323
|
+
debug('stream chunk, size %d, chunk index %d, stream size %d\n%s...... only show 512 bytes ......',
|
|
324
|
+
chunk.length, chunkCount, streamSize, hex(chunk.slice(0, 512)));
|
|
325
|
+
} else {
|
|
326
|
+
debug('stream chunk, size %d, chunk index %d, stream size %d\n%s',
|
|
327
|
+
chunk.length, chunkCount, streamSize, hex(chunk));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
stream.on('end', function () {
|
|
333
|
+
buffers.push(NEW_LINE_BUFFER);
|
|
334
|
+
bufferSize += NEW_LINE_BUFFER.length;
|
|
335
|
+
const chunk = Buffer.concat(buffers, bufferSize);
|
|
336
|
+
self.emit('data', chunk);
|
|
337
|
+
chunkCount++;
|
|
338
|
+
if (chunk.length > 512) {
|
|
339
|
+
debug('stream end, size %d, chunk index %d, stream size %d\n%s...... only show 512 bytes ......',
|
|
340
|
+
chunk.length, chunkCount, streamSize, hex(chunk.slice(0, 512)));
|
|
341
|
+
} else {
|
|
342
|
+
debug('stream end, size %d, chunk index %d, stream size %d\n%s',
|
|
343
|
+
chunk.length, chunkCount, streamSize, hex(chunk));
|
|
344
|
+
}
|
|
254
345
|
return process.nextTick(self.drain.bind(self));
|
|
255
346
|
});
|
|
256
347
|
stream.resume();
|
|
@@ -262,14 +353,22 @@ FormStream.prototype._emitEnd = function () {
|
|
|
262
353
|
// --{boundary}--\r\n
|
|
263
354
|
this.emit('data', this._endData);
|
|
264
355
|
this.emit('end');
|
|
356
|
+
if (debug.enabled) {
|
|
357
|
+
debug('end boundary\n%s', this._endData.toString());
|
|
358
|
+
}
|
|
265
359
|
};
|
|
266
360
|
|
|
267
361
|
FormStream.prototype.drain = function () {
|
|
362
|
+
// debug('drain');
|
|
268
363
|
this._emitBuffers();
|
|
269
364
|
|
|
270
365
|
var item = this._streams.shift();
|
|
271
366
|
if (item) {
|
|
272
|
-
this.
|
|
367
|
+
if (this._minChunkSize && this._minChunkSize > 0) {
|
|
368
|
+
this._emitStreamWithChunkSize(item, this._minChunkSize);
|
|
369
|
+
} else {
|
|
370
|
+
this._emitStream(item);
|
|
371
|
+
}
|
|
273
372
|
} else {
|
|
274
373
|
this._emitEnd();
|
|
275
374
|
}
|
|
@@ -278,6 +377,7 @@ FormStream.prototype.drain = function () {
|
|
|
278
377
|
};
|
|
279
378
|
|
|
280
379
|
FormStream.prototype.resume = function () {
|
|
380
|
+
// debug('resume');
|
|
281
381
|
this.paused = false;
|
|
282
382
|
|
|
283
383
|
if (!this._draining) {
|
|
@@ -290,4 +390,5 @@ FormStream.prototype.resume = function () {
|
|
|
290
390
|
|
|
291
391
|
FormStream.prototype.close = FormStream.prototype.destroy = function () {
|
|
292
392
|
this.emit('destroy');
|
|
393
|
+
// debug('destroy or close');
|
|
293
394
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "formstream",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A multipart/form-data encoded stream, helper for file upload.",
|
|
5
5
|
"main": "lib/formstream.js",
|
|
6
6
|
"types": "types/formstream.d.ts",
|
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"test": "egg-bin test",
|
|
13
13
|
"cov": "egg-bin cov",
|
|
14
|
-
"ci": "npm run lint && npm run tsd && npm run cov",
|
|
14
|
+
"ci": "npm run lint && npm run tsd && npm run cov && NODE_DEBUG=formstream npm run cov",
|
|
15
15
|
"lint": "jshint .",
|
|
16
|
-
"tsd": "tsd"
|
|
16
|
+
"tsd": "tsd",
|
|
17
|
+
"contributor": "git-contributor"
|
|
17
18
|
},
|
|
18
19
|
"repository": {
|
|
19
20
|
"type": "git",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"dependencies": {
|
|
32
33
|
"destroy": "^1.0.4",
|
|
33
34
|
"mime": "^2.5.2",
|
|
35
|
+
"node-hex": "^1.0.1",
|
|
34
36
|
"pause-stream": "~0.0.11"
|
|
35
37
|
},
|
|
36
38
|
"devDependencies": {
|
|
@@ -38,6 +40,7 @@
|
|
|
38
40
|
"connect-multiparty": "1",
|
|
39
41
|
"egg-bin": "^5.6.1",
|
|
40
42
|
"express": "^4.16.4",
|
|
43
|
+
"git-contributor": "^2.1.5",
|
|
41
44
|
"jshint": "^2.13.6",
|
|
42
45
|
"pedding": "1",
|
|
43
46
|
"should": "4",
|
package/types/formstream.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ declare class FormStream extends Stream {
|
|
|
7
7
|
* @param name Name of field
|
|
8
8
|
* @param value Value of field
|
|
9
9
|
*/
|
|
10
|
-
field(name: string, value: string): this
|
|
10
|
+
field(name: string, value: string, contentType?: string): this
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Add a local file to be uploaded to the form.
|
|
@@ -64,9 +64,14 @@ declare class FormStream extends Stream {
|
|
|
64
64
|
headers(additionalHeaders?: Record<string, any>): Record<string, any>
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
interface FormStreamOptions {
|
|
68
|
+
/** min chunk size to emit data event */
|
|
69
|
+
minChunkSize?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
67
72
|
declare const formStream: {
|
|
68
|
-
new (): FormStream
|
|
69
|
-
(): FormStream
|
|
73
|
+
new (options?: FormStreamOptions): FormStream
|
|
74
|
+
(options?: FormStreamOptions): FormStream
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
interface formStream extends FormStream {}
|