How to attach a file in nodejs /node-fetch POST request.I want to invoke an API which import a file (.xls or csv). How can I do this using Node-fetch / nodejs.
问题:
回答1:
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--
回答2:
There is one thing to add to Hugues M.'s answer. File upload with FormData
is not supported by node-fetch
. Instead, you need to use other libraries such as request
or request-promise
. Below is a code snippet for uploading a file using request-promise
library. resolveWithFullResponse
option gives you the raw response. Without this, the promise returns just the body of the response.
let rp = require('request-promise')
var formData = {
file: fs.createReadStream('foo.txt'),
}
let options = {
uri:'http://httpbin.org/post',
formData: formData,
resolveWithFullResponse: true
}
rp.post(options).then((response) => {
// handle response here
})
回答3:
This is a express server that streams a local file to the response.
var fs = require('fs');
var express = require('express')();
express.get('/',function(req,res){
var readStream = fs.createReadStream('./package.json');
readStream.pipe(res);
})
express.listen(2000);