node.jsdownloadstreamfs

How can i save a file i download using fetch with fs


I try downloading files with the fetch() function from github.
Then i try to save the fetched file Stream as a file with the fs-module.
When doing it, i get this error:

TypeError [ERR_INVALID_ARG_TYPE]: The "transform.writable" property must be an instance of WritableStream. Received an instance of WriteStream

My problem is, that i don't know the difference between WriteStream and WritableStream or how to convert them.

This is the code i run:

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

Node.js: v18.7.0


Solution

  • Good question. Web streams are something new, and they are different way of handling streams. WritableStream tells us that we can create WritableStreams as follows:

    import {
      WritableStream
    } from 'node:stream/web';
    
    const stream = new WritableStream({
      write(chunk) {
        console.log(chunk);
      }
    });
    

    Then, you could create a custom stream that writes each chunk to disk. An easy way could be:

    function getFileWritableStream(filePath) {
      const downloadWriteStream = fs.createWriteStream(filePath);
    
      /* This adapter is needed because the method .pipeTo() only
      accepts an instance of WritableStream.
      */
      return new WritableStream({
        write: chunk => downloadWriteStream(chunk)
      });
    }
    
    async function downloadFile(link, filepath = './download.blob') {
      const response = await fetch(link);
      const body = response.body;
      const fileWritableStream = getFileWritableStream(filepath);
      await body.pipeTo(fileWritableStream);
    }