Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pipe one readable stream into two writable streams at once in Node.js?

The goal is to:

  1. Create a file read stream.
  2. Pipe it to gzip (zlib.createGzip())
  3. Then pipe the read stream of zlib output to:

    1) HTTP response object

    2) and writable file stream to save the gzipped output.

Now I can do down to 3.1:

var gzip = zlib.createGzip(),
    sourceFileStream = fs.createReadStream(sourceFilePath),
    targetFileStream = fs.createWriteStream(targetFilePath);

response.setHeader('Content-Encoding', 'gzip');

sourceFileStream.pipe(gzip).pipe(response);

... which works fine, but I need to also save the gzipped data to a file so that I don't need to regzip every time and be able to directly stream the gzipped data as a response.

So how do I pipe one readable stream into two writable streams at once in Node?

Would sourceFileStream.pipe(gzip).pipe(response).pipe(targetFileStream); work in Node 0.8.x?

like image 672
Eye Avatar asked Jan 05 '13 15:01

Eye


People also ask

What is the correct way to pipe a readable stream and a writable stream node?

To consume a readable stream, we can use the pipe / unpipe methods, or the read / unshift / resume methods. To consume a writable stream, we can make it the destination of pipe / unpipe , or just write to it with the write method and call the end method when we're done.

How do you switch between modes in readable stream mode?

One of the ways of switching the mode of a stream to flowing is to attach a 'data' event listener. A way to switch the readable stream to a flowing mode manually is to call the stream. resume method.

Which stream can be used for both read and write operation in node JS?

Duplex − Stream which can be used for both read and write operation.

What is piping in streams node JS?

Pipes can be used to connect multiple streams together. One of the most common example is to pipe the read and write stream together for the transfer of data from one file to the other. Node. js is often also tagged as an event driven framework, and it's very easy to define events in Node. js.


2 Answers

Pipe chaining/splitting doesn't work like you're trying to do here, sending the first to two different subsequent steps:

sourceFileStream.pipe(gzip).pipe(response);

However, you can pipe the same readable stream into two writeable streams, eg:

var fs = require('fs');

var source = fs.createReadStream('source.txt');
var dest1 = fs.createWriteStream('dest1.txt');
var dest2 = fs.createWriteStream('dest2.txt');

source.pipe(dest1);
source.pipe(dest2);
like image 144
hunterloftis Avatar answered Oct 12 '22 04:10

hunterloftis


I found that zlib returns a readable stream which can be later piped into multiple other streams. So I did the following to solve the above problem:

var sourceFileStream = fs.createReadStream(sourceFile);
// Even though we could chain like
// sourceFileStream.pipe(zlib.createGzip()).pipe(response);
// we need a stream with a gzipped data to pipe to two
// other streams.
var gzip = sourceFileStream.pipe(zlib.createGzip());

// This will pipe the gzipped data to response object
// and automatically close the response object.
gzip.pipe(response);

// Then I can pipe the gzipped data to a file.
gzip.pipe(fs.createWriteStream(targetFilePath));
like image 22
Eye Avatar answered Oct 12 '22 04:10

Eye