【问题标题】:How to send a file in request node-fetch or Node?如何在请求节点获取或节点中发送文件?
【发布时间】:2017-10-16 17:17:32
【问题描述】:

如何在 Node 或 Node Fetch POST 请求中附加文件?我正在尝试调用将导入 CSV 或 XLS 文件的 API。这可以使用 Node 或 Node Fetch 吗?

【问题讨论】:

  • 只是要明确一点:您想创建一个端点,该端点将接受文件作为输入并使用 node-fetch 在您的 nodejs 服务器上存储/处理它?
  • 嗯,这是我对这个问题的理解:它不涉及 nodejs 服务器。他们想在 nodejs 程序中使用node-fetch 将文件发布到服务(哪个服务不重要)(这样从这个角度来看,该程序将是一个 http 客户端。它也可能是用于其他目的的服务器,但那是无关)。

标签: node.js file post node-fetch


【解决方案1】:

我正在寻找如何使用node-fetch 通过multipart/form-datatheir GitHub docs actually shows how to do this 上传文件。下面是修改后的示例,展示了如何将缓冲区附加到 FormData 并上传。

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));

与我一样在 Google 上搜索“node-fetch upload file multipart”的其他人分享此内容。

【讨论】:

  • 非常感谢@rico-kahler,我已经删除了我的反对票。请注意其他人,个人永远不会使用缓冲区或同步读取文件,因为大文件将超过 RAM 并需要大量时间来读取。不幸的是,form-data 包似乎不适用于流,我认为问题是由于请求标头中缺少内容长度造成的,并且内容长度计算起来有些复杂。
  • 它对我有用,但不是 append('file') 需要添加 append('upload')
  • 如果我们要发送带有标头的请求,上述请求将不起作用。你能展示如何用标题发送它吗?
  • @ChandaraChea 将标头添加到 fetch API 选项:github.com/node-fetch/node-fetch#fetch-options 例如fetch('/blah', { headers: { /* ... */} })
  • 传递 contentType、name 和 fileName 选项是我发布的 API 接受文件的原因。谢谢!
【解决方案2】:

这是一个快速服务器,将本地文件流式传输到响应。

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】:

README.md 说:

在请求和响应中使用本机流作为正文。

还有sources indicate it supports several types,比如StreamBufferBlob... 并且还会尝试强制转换为String 用于其他类型。

下面的 sn-p 显示了 3 个示例,所有示例都可以使用 v1.7.1 或 2.0.0-alpha5(另请参阅下面的其他示例,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);
});

这里是foo.txt

hello world!
how do you do?

注意:http://httpbin.org/post 回复 JSON,其中包含已发送请求的详细信息。

结果:

{
  "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"
}

如果您需要将文件作为具有更多参数的表单的一部分发送,您可以尝试:

  • npm install form-data
  • 传递一个FormData对象作为body(FormDataStream的一种,通过CombinedStreamlibrary
  • 不要在选项中传递header(与上面的示例不同)

然后就可以了:

const formData = new FormData();
formData.append('file', fs.createReadStream('foo.txt'));
formData.append('blah', 42);
fetch('http://httpbin.org/post', {
    method: 'POST',
    body: formData
})

结果(只显示发送的内容):

----------------------------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--

【讨论】:

  • 有没有办法在不使用 form-data 模块的情况下形成上述结构,然后可以由 node-fetch body 参数使用?
  • @Avinash 你必须实现the spec ??‍♂️。如果您的输入不是任意复杂的,它可能很简单。 Here 是一个更容易阅读的解释。
  • @HuguesM。 'filename="foo.txt" 是如何进入正文的?我只看到正在添加的数据。
  • 如何从传入的请求对象中获取多部分?
猜你喜欢
  • 2018-06-26
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 2015-09-15
  • 1970-01-01
相关资源
最近更新 更多