如何使用 Fetch API 下载和保存文件? (Node.js)

Posted

技术标签:

【中文标题】如何使用 Fetch API 下载和保存文件? (Node.js)【英文标题】:How can I download and save a file using the Fetch API? (Node.js) 【发布时间】:2016-10-03 12:51:58 【问题描述】:

我有一个可能很大 (100+ Mb) 文件的 url,如何使用 fetch 将其保存在本地目录中?

我环顾四周,但似乎没有很多关于如何做到这一点的资源/教程。

谢谢!

【问题讨论】:

Node.js 没有集成 Fetch。 为什么要抓取? Node 支持 http 吗? 我正在创建一个 Electron 应用,支持 fetch。为什么要 fetch 而不是纯 http,因为它更容易使用(或者到目前为止看起来如此)。 如果有人在浏览器中寻找使用 fetch api 保存文件的方法(并遇到了这个答案),那么请看这里:***.com/a/42274086/350384 【参考方案1】:

使用 Fetch API,您可以编写一个可以从如下 URL 下载的函数:

const downloadFile = (async (url, path) => 
  const res = await fetch(url);
  const fileStream = fs.createWriteStream(path);
  await new Promise((resolve, reject) => 
      res.body.pipe(fileStream);
      res.body.on("error", reject);
      fileStream.on("finish", resolve);
    );
);

【讨论】:

您甚至可以通过编写 res.body.on('error', reject);fileStream.on('finish', resolve); 来缩短它。【参考方案2】:

如果您想避免像其他非常好的答案那样明确地做出承诺,并且可以构建整个 100+ MB 文件的缓冲区,那么您可以做一些更简单的事情:

const fetch = require('node-fetch');
const writeFile = require('fs');
const promisify = require('util');
const writeFilePromise = promisify(writeFile);

function downloadFile(url, outputPath) 
  return fetch(url)
      .then(x => x.arrayBuffer())
      .then(x => writeFilePromise(outputPath, Buffer.from(x)));

但另一个答案会更节省内存,因为它将接收到的数据流直接传输到文件中,而不会将所有数据流累积到缓冲区中。

【讨论】:

【参考方案3】:
const createWriteStream = require('fs');
const pipeline = require('stream/promises');
const fetch = require('node-fetch');

const downloadFile = async (url, path) => pipeline(
    (await fetch(url)).body,
    createWriteStream(path)
);

【讨论】:

我收到错误TypeError: Cannot read property 'on' of undefined at destroyer (internal/streams/pipeline.js:23:10)

以上是关于如何使用 Fetch API 下载和保存文件? (Node.js)的主要内容,如果未能解决你的问题,请参考以下文章

Javascript Fetch API - 如何将输出作为对象保存到变量(不是承诺)

如何使用 cloudinary API 下载文件?

使用 Fetch API 和 fs.createWriteStream 对文件进行流式响应

如何使用 JavaScript 下载大文件

如何使用 fetch API 发布多个文件?

使用 Javascript Fetch API 发送的快速解析文件