Permalink
August 3, 2022 13:36
Newer
100644
350 lines (261 sloc)
11.2 KB
Ignoring revisions in .git-blame-ignore-revs.
1
# Form-Data [](https://www.npmjs.com/package/form-data) [](https://gitter.im/form-data/form-data)
2
3
A library to create readable ```"multipart/form-data"``` streams. Can be used to submit forms and file uploads to other web applications.
4
5
The API of this library is inspired by the [XMLHttpRequest-2 FormData Interface][xhr2-fd].
6
7
[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface
8
9
[](https://travis-ci.org/form-data/form-data)
10
[](https://travis-ci.org/form-data/form-data)
11
[](https://travis-ci.org/form-data/form-data)
12
13
[](https://coveralls.io/github/form-data/form-data?branch=master)
14
[](https://david-dm.org/form-data/form-data)
15
16
## Install
17
18
```
19
npm install --save form-data
20
```
21
22
## Usage
23
24
In this example we are constructing a form with 3 fields that contain a string,
25
a buffer and a file stream.
26
27
``` javascript
28
var FormData = require('form-data');
29
var fs = require('fs');
30
31
var form = new FormData();
32
form.append('my_field', 'my value');
33
form.append('my_buffer', new Buffer(10));
34
form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
35
```
36
37
Also you can use http-response stream:
38
39
``` javascript
40
var FormData = require('form-data');
41
var http = require('http');
42
43
var form = new FormData();
44
45
http.request('http://nodejs.org/images/logo.png', function(response) {
46
form.append('my_field', 'my value');
47
form.append('my_buffer', new Buffer(10));
48
form.append('my_logo', response);
49
});
50
```
51
52
Or @mikeal's [request](https://github.com/request/request) stream:
53
54
``` javascript
55
var FormData = require('form-data');
56
var request = require('request');
57
58
var form = new FormData();
59
60
form.append('my_field', 'my value');
61
form.append('my_buffer', new Buffer(10));
62
form.append('my_logo', request('http://nodejs.org/images/logo.png'));
63
```
64
65
In order to submit this form to a web application, call ```submit(url, [callback])``` method:
66
67
``` javascript
68
form.submit('http://example.org/', function(err, res) {
69
// res – response object (http.IncomingMessage) //
70
res.resume();
71
});
72
73
```
74
75
For more advanced request manipulations ```submit()``` method returns ```http.ClientRequest``` object, or you can choose from one of the alternative submission methods.
76
77
### Custom options
78
79
You can provide custom options, such as `maxDataSize`:
80
81
``` javascript
82
var FormData = require('form-data');
83
84
var form = new FormData({ maxDataSize: 20971520 });
85
form.append('my_field', 'my value');
86
form.append('my_buffer', /* something big */);
87
```
88
89
List of available options could be found in [combined-stream](https://github.com/felixge/node-combined-stream/blob/master/lib/combined_stream.js#L7-L15)
90
91
### Alternative submission methods
92
93
You can use node's http client interface:
94
95
``` javascript
96
var http = require('http');
97
98
var request = http.request({
99
method: 'post',
100
host: 'example.org',
101
path: '/upload',
102
headers: form.getHeaders()
103
});
104
105
form.pipe(request);
106
107
request.on('response', function(res) {
108
console.log(res.statusCode);
109
});
110
```
111
112
Or if you would prefer the `'Content-Length'` header to be set for you:
113
114
``` javascript
115
form.submit('example.org/upload', function(err, res) {
116
console.log(res.statusCode);
117
});
118
```
119
120
To use custom headers and pre-known length in parts:
121
122
``` javascript
123
var CRLF = '\r\n';
124
var form = new FormData();
125
126
var options = {
127
header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,
128
knownLength: 1
129
};
130
131
form.append('my_buffer', buffer, options);
132
133
form.submit('http://example.com/', function(err, res) {
134
if (err) throw err;
135
console.log('Done');
136
});
137
```
138
139
Form-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide "file"-related information manually:
140
141
``` javascript
142
someModule.stream(function(err, stdout, stderr) {
143
if (err) throw err;
144
145
var form = new FormData();
146
147
form.append('file', stdout, {
148
filename: 'unicycle.jpg', // ... or:
149
filepath: 'photos/toys/unicycle.jpg',
150
contentType: 'image/jpeg',
151
knownLength: 19806
152
});
153
154
form.submit('http://example.com/', function(err, res) {
155
if (err) throw err;
156
console.log('Done');
157
});
158
});
159
```
160
161
The `filepath` property overrides `filename` and may contain a relative path. This is typically used when uploading [multiple files from a directory](https://wicg.github.io/entries-api/#dom-htmlinputelement-webkitdirectory).
162
163
For edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter:
164
165
``` javascript
166
form.submit({
167
host: 'example.com',
168
path: '/probably.php?extra=params',
169
auth: 'username:password'
170
}, function(err, res) {
171
console.log(res.statusCode);
172
});
173
```
174
175
In case you need to also send custom HTTP headers with the POST request, you can use the `headers` key in first parameter of `form.submit()`:
176
177
``` javascript
178
form.submit({
179
host: 'example.com',
180
path: '/surelynot.php',
181
headers: {'x-test-header': 'test-header-value'}
182
}, function(err, res) {
183
console.log(res.statusCode);
184
});
185
```
186
187
### Methods
188
189
- [_Void_ append( **String** _field_, **Mixed** _value_ [, **Mixed** _options_] )](https://github.com/form-data/form-data#void-append-string-field-mixed-value--mixed-options-).
190
- [_Array_ getHeaders( [**Array** _userHeaders_] )](https://github.com/form-data/form-data#array-getheaders-array-userheaders-)
191
- [_String_ getBoundary()](https://github.com/form-data/form-data#string-getboundary)
192
- [_Buffer_ getBuffer()](https://github.com/form-data/form-data#buffer-getbuffer)
193
- [_Integer_ getLengthSync()](https://github.com/form-data/form-data#integer-getlengthsync)
194
- [_Integer_ getLength( **function** _callback_ )](https://github.com/form-data/form-data#integer-getlength-function-callback-)
195
- [_Boolean_ hasKnownLength()](https://github.com/form-data/form-data#boolean-hasknownlength)
196
- [_Request_ submit( _params_, **function** _callback_ )](https://github.com/form-data/form-data#request-submit-params-function-callback-)
197
- [_String_ toString()](https://github.com/form-data/form-data#string-tostring)
198
199
#### _Void_ append( **String** _field_, **Mixed** _value_ [, **Mixed** _options_] )
200
Append data to the form. You can submit about any format (string, integer, boolean, buffer, etc.). However, Arrays are not supported and need to be turned into strings by the user.
201
```javascript
202
var form = new FormData();
203
form.append( 'my_string', 'my value' );
204
form.append( 'my_integer', 1 );
205
form.append( 'my_boolean', true );
206
form.append( 'my_buffer', new Buffer(10) );
207
form.append( 'my_array_as_json', JSON.stringify( ['bird','cute'] ) )
208
```
209
210
You may provide a string for options, or an object.
211
```javascript
212
// Set filename by providing a string for options
213
form.append( 'my_file', fs.createReadStream('/foo/bar.jpg'), 'bar.jpg' );
214
215
// provide an object.
216
form.append( 'my_file', fs.createReadStream('/foo/bar.jpg'), {filename: 'bar.jpg', contentType: 'image/jpeg', knownLength: 19806} );
217
```
218
219
#### _Array_ getHeaders( [**Array** _userHeaders_] )
220
This method ads the correct `content-type` header to the provided array of `userHeaders`.
221
222
#### _String_ getBoundary()
223
Return the boundary of the formData. A boundary consists of 26 `-` followed by 24 numbers
224
for example:
225
```javascript
226
--------------------------515890814546601021194782
227
```
228
_Note: The boundary must be unique and may not appear in the data._
229
230
#### _Buffer_ getBuffer()
231
Return the full formdata request package, as a Buffer. You can insert this Buffer in e.g. Axios to send multipart data.
232
```javascript
233
var form = new FormData();
234
form.append( 'my_buffer', Buffer.from([0x4a,0x42,0x20,0x52,0x6f,0x63,0x6b,0x73]) );
235
form.append( 'my_file', fs.readFileSync('/foo/bar.jpg') );
236
237
axios.post( 'https://example.com/path/to/api',
238
form.getBuffer(),
239
form.getHeaders()
240
)
241
```
242
**Note:** Because the output is of type Buffer, you can only append types that are accepted by Buffer: *string, Buffer, ArrayBuffer, Array, or Array-like Object*. A ReadStream for example will result in an error.
243
244
#### _Integer_ getLengthSync()
245
Same as `getLength` but synchronous.
246
247
_Note: getLengthSync __doesn't__ calculate streams length._
248
249
#### _Integer_ getLength( **function** _callback_ )
250
Returns the `Content-Length` async. The callback is used to handle errors and continue once the length has been calculated
251
```javascript
252
this.getLength(function(err, length) {
253
if (err) {
254
this._error(err);
255
return;
256
}
257
258
// add content length
259
request.setHeader('Content-Length', length);
260
261
...
262
}.bind(this));
263
```
264
265
#### _Boolean_ hasKnownLength()
266
Checks if the length of added values is known.
267
268
#### _Request_ submit( _params_, **function** _callback_ )
269
Submit the form to a web application.
270
```javascript
271
var form = new FormData();
272
form.append( 'my_string', 'Hello World' );
273
274
form.submit( 'http://example.com/', function(err, res) {
275
// res – response object (http.IncomingMessage) //
276
res.resume();
277
} );
278
```
279
280
#### _String_ toString()
281
Returns the form data as a string. Don't use this if you are sending files or buffers, use `getBuffer()` instead.
282
283
### Integration with other libraries
284
285
#### Request
286
287
Form submission using [request](https://github.com/request/request):
288
289
```javascript
290
var formData = {
291
my_field: 'my_value',
292
my_file: fs.createReadStream(__dirname + '/unicycle.jpg'),
293
};
294
295
request.post({url:'http://service.com/upload', formData: formData}, function(err, httpResponse, body) {
296
if (err) {
297
return console.error('upload failed:', err);
298
}
299
console.log('Upload successful! Server responded with:', body);
300
});
301
```
302
303
For more details see [request readme](https://github.com/request/request#multipartform-data-multipart-form-uploads).
304
305
#### node-fetch
306
307
You can also submit a form using [node-fetch](https://github.com/bitinn/node-fetch):
308
309
```javascript
310
var form = new FormData();
311
312
form.append('a', 1);
313
314
fetch('http://example.com', { method: 'POST', body: form })
315
.then(function(res) {
316
return res.json();
317
}).then(function(json) {
318
console.log(json);
319
});
320
```
321
322
#### axios
323
324
In Node.js you can post a file using [axios](https://github.com/axios/axios):
325
```javascript
326
const form = new FormData();
327
const stream = fs.createReadStream(PATH_TO_FILE);
328
329
form.append('image', stream);
330
331
// In Node.js environment you need to set boundary in the header field 'Content-Type' by calling method `getHeaders`
332
const formHeaders = form.getHeaders();
333
334
axios.post('http://example.com', form, {
335
headers: {
336
...formHeaders,
337
},
338
})
339
.then(response => response)
340
.catch(error => error)
341
```
342
343
## Notes
344
345
- ```getLengthSync()``` method DOESN'T calculate length for streams, use ```knownLength``` options as workaround.
346
- Starting version `2.x` FormData has dropped support for `node@0.10.x`.
347
348
## License
349
350
Form-Data is released under the [MIT](License) license.