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?
fetch() function. In NodeJS, several packages/libraries can achieve the same result. One of them is the node-fetch package. node-fetch is a lightweight module that enables us to use the fetch() function in NodeJS, with very similar functionality as window.
Fetch is already available as an experimental feature in Node v17. If you're interested in trying it out before the main release, you'll need to first download and upgrade your Node. js version to 17.5.
To send data, fetch() uses the body property for a post request to send data to the endpoint, while Axios uses the data property. The data in fetch() is transformed to a string using the JSON. stringify method.
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
FormData
object as body (FormData
is a kind of Stream
, via CombinedStream
library)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--
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With