1

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.

Martin Cup
  • 2,399
  • 1
  • 21
  • 32
  • `stream.Readable.fromWeb((await fetch("https://stackoverflow.com")).body).pipe(process.stdout)` works for me, where `fetch(...).body` is a `ReadableStream`. Is your `stream` not of the same type? – Heiko Theißen Dec 14 '22 at 17:21
  • This also works for me. So probably stream is not the same type despite it has the same name. 'The "readableStream" argument must be an instance of ReadableStream. Received an instance of ReadableStream' error also indicates this. I discovered now, that I also can get an arrayBuffer from the framework which is easily written as a file. But the ReadableStream myth continues. – Martin Cup Dec 14 '22 at 17:46
  • This same question was answered here: https://stackoverflow.com/a/73338676/266535 – styfle May 02 '23 at 14:42

1 Answers1

0

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