How to send a file in request node-fetch or nodejs

2019-03-26 08:18发布

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.

3条回答
倾城 Initia
2楼-- · 2019-03-26 08:27

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);
查看更多
来,给爷笑一个
3楼-- · 2019-03-26 08:35

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 of Stream, via CombinedStream 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--
查看更多
成全新的幸福
4楼-- · 2019-03-26 08:36

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 
})
查看更多
登录 后发表回答