nodejs ReadableStream pipeTo file with WritableStream

2.4k views Asked by At

I'm trying to write an uploaded file in nodejs 18.12. from a ReadableStream with pipeTo to a file on the harddrive. But the following fails

const fs = require('fs');
var path = __dirname + '/test.png';
const writeStream = fs.createWriteStream(path);
// stream is a ReadableStream object
stream.pipeTo(writeStream).on('finish', async () => {
      console.log('DONE');
})

with

TypeError: ReadableStream.prototype.pipeTo's first argument must be a WritableStream

But I have not found any docs how to work correcty with pipeTo and to store the data into a file. Searching for WritableStream didn't help me either. I'm using graphql-yoga 3.x and the ReadableStream is what I'm getting from the framework.

I also tried a solution from here to convert the stream into a Readable

const { Readable } = require('node:stream');
var readStream = new Readable().wrap(stream);

which failed with stream.on is not a function

I also tried a solution from here with Readable.fromWeb

const writeStream = fs.createWriteStream(path);
var readStream = Readable.fromWeb(stream);
readStream.pipe(writeStream).on('finish', async () => {
  console.log('DONE');
})

which got me this strange error:

TypeError: The "readableStream" argument must be an instance of ReadableStream. 
Received an instance of ReadableStream

I also now found an example on graphql-yoga website for v2, but it wont work neither.

1

There are 1 answers

0
techdobycon On

The pipe flow looks like this:

ReadableStream -pipeTo-> TransformStream -pipeTo-> WriteableStream

But you have to create a clean WritableStream, this is like a buffer to Write something to somewhere.

A readableStream is a Stream that read bytes from some object, in your case read a photo from File is a readable Stream, like that:

var http = require('http');
var fs = require('fs');

http.createServer(function(req, res) {
  // The filename is simple the local directory and tacks on the requested url
  var filename = __dirname+"/test.png";

  // This line opens the file as a readable stream
  var readStream = fs.createReadStream(filename);

  // This will wait until we know the readable stream is actually valid before piping
  readStream.on('open', function () {
    // This just pipes the read stream to the response object (which goes to the client)
    readStream.pipe(res);
  });

  // This catches any errors that happen while creating the readable stream (usually invalid names)
  readStream.on('error', function(err) {
    res.end(err);
  });
}).listen(8080);

this code convert a file into a readstream, after that you have to create a WriteStream for another reason, for example (in my case is the response), but you can write another file for example to pipe to this, like this:

var http = require('http');
var fs = require('fs');

http.createServer(function(req, res) {
  // The filename is simple the local directory and tacks on the requested url
  var filename = __dirname+"/test.png";
  var filename2 = __dirname+"/test2.png";

  // This line opens the file as a readable stream
  var readStream = fs.createReadStream(filename);
  var writeStream = fs.createWriteStream(filename2);
  // This will wait until we know the readable stream is actually valid before piping
  readStream.on('open', function () {
    // This just pipes the read stream to the write stream (duplicate the file)
    readStream.pipe(writeStream);
  });

  // This catches any errors that happen while creating the readable stream (usually invalid names)
  readStream.on('error', function(err) {
    res.end(err);
  });
  res.end("it's all");
}).listen(8080);