How do I attach a file in Node or Node Fetch POST request? I am trying to invoke an API which will import a CSV or XLS file. Is this possible using Node or Node Fetch?
-
just to be clear: you want to create an endpoint which will accept file as input and store / process it on your nodejs server using [node-fetch](https://www.npmjs.com/package/node-fetch) ? – Kunal Parekh Jun 19 '17 at 07:54
-
2Hmm here is my understanding of the question: it does not involve a nodejs server. They want to POST a file to a service (which service is not important) using `node-fetch` from within a nodejs program (so that program would be an http client from that perspective. It could also be a server for other purposes but that is irrelevant). – Hugues M. Jun 21 '17 at 17:38
2 Answers
README.md
says:
Use native stream for body, on both request and response.
And sources indicate it supports several types, like Stream
, Buffer
, Blob
... and also will try to coerce as String
for other types.
Below snippet shows 3 examples, all work, with v1.7.1 or 2.0.0-alpha5 (see also other example further down with FormData
):
let fetch = require('node-fetch');
let fs = require('fs');
const stats = fs.statSync("foo.txt");
const fileSizeInBytes = stats.size;
// You can pass any of the 3 objects below as body
let readStream = fs.createReadStream('foo.txt');
//var stringContent = fs.readFileSync('foo.txt', 'utf8');
//var bufferContent = fs.readFileSync('foo.txt');
fetch('http://httpbin.org/post', {
method: 'POST',
headers: {
"Content-length": fileSizeInBytes
},
body: readStream // Here, stringContent or bufferContent would also work
})
.then(function(res) {
return res.json();
}).then(function(json) {
console.log(json);
});
Here is foo.txt
:
hello world!
how do you do?
Note: http://httpbin.org/post
replies with JSON that contains details on request that was sent.
Result:
{
"args": {},
"data": "hello world!\nhow do you do?\n",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip,deflate",
"Connection": "close",
"Content-Length": "28",
"Host": "httpbin.org",
"User-Agent": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)"
},
"json": null,
"origin": "86.247.18.156",
"url": "http://httpbin.org/post"
}
If you need to send a file as part of a form with more parameters, you can try:
npm install form-data
- pass a
FormData
object as body (FormData
is a kind ofStream
, viaCombinedStream
library) - do not pass
header
in the options (unlike examples above)
and then this works:
const formData = new FormData();
formData.append('file', fs.createReadStream('foo.txt'));
formData.append('blah', 42);
fetch('http://httpbin.org/post', {
method: 'POST',
body: formData
})
Result (just showing what is sent):
----------------------------802616704485543852140629
Content-Disposition: form-data; name="file"; filename="foo.txt"
Content-Type: text/plain
hello world!
how do you do?
----------------------------802616704485543852140629
Content-Disposition: form-data; name="blah"
42
----------------------------802616704485543852140629--

- 19,846
- 6
- 37
- 65
-
Is there way of forming the above structure without using form-data module, that can be then consumed by the node-fetch body parameter? – Avinash Mar 02 '20 at 14:31
-
@Avinash You would have to implement [the spec](https://www.ietf.org/rfc/rfc2388.txt) ♂️. If your input is not arbitrarily complex, it might be straightforward. [Here](https://ec.haxx.se/http/http-multipart) is an easier to read explanation. – Hugues M. Mar 14 '20 at 18:42
-
@HuguesM. How did 'filename="foo.txt" get into the body? I only see the data being added. – Jim B. Dec 14 '20 at 03:18
-
How would you fetch the multipart portion from an incoming request object? – Woodsman Mar 04 '21 at 15:50
I was looking for how to use node-fetch
to upload files via multipart/form-data
and their GitHub docs actually shows how to do this. Below is modified example showing how to attach a buffer to FormData
and upload that.
const FormData = require('form-data');
const form = new FormData();
const buffer = // e.g. `fs.readFileSync('./fileLocation');
const fileName = 'test.txt';
form.append('file', buffer, {
contentType: 'text/plain',
name: 'file',
filename: fileName,
});
fetch('https://httpbin.org/post', { method: 'POST', body: form })
.then(res => res.json())
.then(json => console.log(json));
Sharing this for anyone else who googled "node-fetch upload file multipart" like I did.

- 23
- 5

- 17,616
- 11
- 59
- 85
-
Nice thanks @rico-kahler, I've removed my down vote. Note to others, personally wouldn't ever use a buffer or read files synchronously, since large files will exceed RAM and take a significant amount of time to read. Unfortunately that form-data package doesn't seem to work well with streams, I think the issue is caused by the lack of a content length in the request header and content length is somewhat complex to calculate. – Ryan Smith May 09 '19 at 20:19
-
It works for me, but instead of append('file') need to add append('upload') – Ruslan Korkin Aug 14 '19 at 11:44
-
the above request doesn't work if we want to send the request with headers. Could you show how to send it with headers? – Chandara Chea Apr 07 '20 at 06:50
-
@ChandaraChea add headers to the fetch API options: https://github.com/node-fetch/node-fetch#fetch-options e.g. `fetch('/blah', { headers: { /* ... */} })` – Rico Kahler Apr 07 '20 at 21:04
-
1passing the contentType, name and fileName options are what made the API I was POSting to accept the file. Thank you! – Iainure Mar 11 '21 at 16:04