如何保存使用 fetch 和 fs 下载的文件

Cuz*_*tte 8 download stream fs node.js

我尝试使用 fetch() 函数从 github 下载文件。
然后我尝试将获取的文件流保存为带有 fs 模块的文件。
执行此操作时,我收到此错误:

TypeError [ERR_INVALID_ARG_TYPE]:“transform.writable”属性必须是 WritableStream 的实例。收到 WriteStream 的实例

我的问题是,我不知道 WriteStream 和 WritableStream 之间的区别或如何转换它们。

这是我运行的代码:

async function downloadFile(link, filename = "download") {
    var response = await fetch(link);
    var body = await response.body;
    var filepath = "./" + filename;
    var download_write_stream = fs.createWriteStream(filepath);
    console.log(download_write_stream.writable);
    await body.pipeTo(download_write_stream);
}
Run Code Online (Sandbox Code Playgroud)

Node.js:v18.7.0

小智 9

好问题。Web 流是新事物,它们是处理流的不同方式。WritableStream告诉我们可以按如下方式创建WritableStream

import {
  WritableStream
} from 'node:stream/web';

const stream = new WritableStream({
  write(chunk) {
    console.log(chunk);
  }
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建一个将每个块写入磁盘的自定义流。一个简单的方法可能是:

const download_write_stream = fs.createWriteStream('./the_path');


const stream = new WritableStream({
  write(chunk) {
    download_write_stream.write(chunk);
  },
});

async function downloadFile(link, filename = 'download') {
  const response = await fetch(link);
  const body = await response.body;
  await body.pipeTo(stream);
}
Run Code Online (Sandbox Code Playgroud)


ant*_*nok 8

您可以使用将Web 流 API中的Readable.fromWeb转换为可与这些方法一起使用的NodeJS流。bodyReadableStreamReadablefs

请注意,readable.pipe立即返回另一个流。要等待它完成,您可以使用 Promise 版本stream.finished将其转换为Promise,或者您可以为'finish''error'事件添加监听器以检测成功或失败。

const fs = require('fs');
const { Readable } = require('stream');
const { finished } = require('stream/promises');

async function downloadFile(link, filepath = './download') {
    const response = await fetch(link);
    const body = Readable.fromWeb(response.body);
    const download_write_stream = fs.createWriteStream(filepath);
    await finished(body.pipe(download_write_stream));
}
Run Code Online (Sandbox Code Playgroud)