【问题标题】:Upload file to a REST API using fetch in native NodeJS在本机 NodeJS 中使用 fetch 将文件上传到 REST API
【发布时间】:2022-10-03 08:32:38
【问题描述】:

我正在尝试使用 NodeJS 中的本机 fetch() API 将文件上传到 REST API。 到目前为止,我已经成功地发出了其他 GET 和 POST 请求,但是这个文件上传给我带来了很多麻烦。

我有以下功能 -

async function uploadDocumentToHub(hub_entity_id, document_path) {
  let formData = new FormData();
  formData.append(\"type\", \"Document\");
  formData.append(\"name\", \"ap_test_document.pdf\");
  formData.append(\"file\", fs.createReadStream(\"ap_test_document.pdf\"));
  formData.append(\"entity_object_id\", hub_entity_id);

  const form_headers = {
    Authorization: auth_code,
    ...formData.getHeaders(),
  };

  console.log(
    `Uploading document ap_test_document.pdf to hub (${hub_entity_id}) `
  );
  console.log(formData);

  let raw_response = await fetch(urls.attachments, {
    method: \"POST\",
    headers: form_headers,
    body: formData,
  });
  
  console.log(raw_response);
}

然后我使用以下代码运行 -

async function async_main() {
  ......
.......
  await uploadDocumentToHub(hub_entity_id, document_path);
}

// main();
async_main();

而且我不断收到以下错误-

node:internal/deps/undici/undici:5536
          p.reject(Object.assign(new TypeError(\"fetch failed\"), { cause: response.error }));
                                 ^

TypeError: fetch failed
    at Object.processResponse (node:internal/deps/undici/undici:5536:34)
    at node:internal/deps/undici/undici:5858:42
    at node:internal/process/task_queues:140:7
    at AsyncResource.runInAsyncScope (node:async_hooks:202:9)
    at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  cause: TypeError: object2 is not iterable
      at action (node:internal/deps/undici/undici:1660:39)
      at action.next (<anonymous>)
      at Object.pull (node:internal/deps/undici/undici:1708:52)
      at ensureIsPromise (node:internal/webstreams/util:172:19)
      at readableStreamDefaultControllerCallPullIfNeeded (node:internal/webstreams/readablestream:1884:5)
      at node:internal/webstreams/readablestream:1974:7
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
}

我对发生了什么以及这个错误是什么感到困惑。有任何想法吗? 以下代码正确上传文件(从邮递员自动生成,一些数据 <removed> 出于安全考虑) -

var axios = require(\'axios\');
var FormData = require(\'form-data\');
var fs = require(\'fs\');
var data = new FormData();
data.append(\'type\', \'Document\');
data.append(\'name\', \'ap_test_document.pdf\');
data.append(\'file\', fs.createReadStream(\'kX3bdHb1G/ap_test_document.pdf\'));
data.append(\'entity_object_id\', \'<id>\');

var config = {
  method: \'post\',
  url: \'<url>\',
  headers: { 
    \'Authorization\': \'<token>\', 
    ...data.getHeaders()
  },
  data : data
};

axios(config)
.then(function (response) {
  console.log(JSON.stringify(response.data));
})
.catch(function (error) {
  console.log(error);
});

一些帮助将不胜感激。

谢谢!

  • Undici\'s (npmjs.com/package/undici) 版本的 fetch API(这是节点开发人员决定使用的)仍处于试验阶段,尚未准备好投入生产。你可能只是触发了一个错误。我会等到他们把它从实验状态中取出来使用内置的提取。请注意,undici 是一个成熟且经过良好测试的库,但它的 API 与 fetch() 非常不同。 fetch API 的实现是新的
  • @slebetman 是的,很公平。我不确定我是否遇到了您建议的错误或我自己设计的问题。现在,我可能只坚持使用 axios 实现(除非我能找到解决方案)。干杯。
  • 如果你不坚持使用 fetch API undici 是非常好的。我最近在我的项目中使用它来替换古老的 request 库,该库已被弃用且不再受支持。 Undici 真的很快。在我的测试中,它比 node-fetch 快大约 10 倍。使用 node-fetch 时,我每秒收到大约 1-2k 个请求,使用 undici 我每秒收到大约 15k 个请求(我需要这个,因为我正在编写压力测试器)

标签: javascript node.js rest fetch


【解决方案1】:

你不能在 Node.js 中使用fetch API,你可以安装axiosnode-fetch

import fetch from 'node-fetch';

const body = {a: 1};

const response = await fetch('https://httpbin.org/post', {
    method: 'post',
    body: JSON.stringify(body),
    headers: {'Content-Type': 'application/json'}
});
const data = await response.json();

console.log(data);```

https://www.npmjs.com/package/node-fetch
https://www.npmjs.com/package/axios

【讨论】:

【解决方案2】:

您可以通过使用fs.readFile 读取文件并将内容转换为Blob 来将文件附加到Node 18 本机Fetch。

以下是我在 TypeScript (YMMV) 中编写的一些伪代码:

import fs from 'fs/promises';

async function createBlobFromFile(path: string): Promise<Blob> {
    const file = await fs.readFile(path);
    return new Blob([file]);
}

const path = '/path/to/file.txt';
const formData = new FormData();
formData.append('file', await createBlobFromFile(path), 'file.txt');

const response = await fetch('https://some.url', {
    method: 'POST',
    body: formData
});

【讨论】:

    猜你喜欢
    • 2020-06-22
    • 2020-09-05
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 2022-11-08
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多