Как направить один читаемый поток сразу в два записываемых потока в Node.js?

Целью является:

  1. Создайте поток чтения файла.
  2. Вставьте его в gzip (zlib.createGzip())
  3. Затем направьте поток чтения вывода zlib на:

    1) HTTP response объект

    2) и записываемый файловый поток для сохранения сжатых данных.

Теперь я могу снизить до 3.1:

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

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

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

... который работает нормально, но мне также нужно сохранить сжатые данные в файл, чтобы мне не нужно было каждый раз повторно архивировать и иметь возможность напрямую передавать сжатые данные в качестве ответа.

Итак, как мне передать один доступный для чтения поток сразу двум доступным для записи потокам в Node?

Будет ли sourceFileStream.pipe(gzip).pipe(response).pipe(targetFileStream); работать в Node 0.8.x?


person Eye    schedule 05.01.2013    source источник


Ответы (3)


Цепочка / разделение каналов не работает так, как вы пытаетесь сделать здесь, отправляя первый на два разных последующих шага:

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

Однако вы можете направить один и тот же читаемый поток в два записываемых потока, например:

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);
person hunterloftis    schedule 05.01.2013
comment
Трубы можно соединять цепью. Ознакомьтесь с документом Zlib nodejs.org/api/zlib.html. Вы можете видеть raw.pipe(zlib.createGzip()).pipe(response); Я знаю решение, которое вы дали, но оно не решает мою проблему, потому что в моем случае у меня нет определенного потока чтения. Данные генерируются zlib во время выполнения, и мне нужно передать их данные в два записываемых потока. - person Eye; 06.01.2013
comment
Трубы соединены цепью? Нет, если учесть, что последний pipe () не работает с первым raw потоком. Это не похоже на jQuery, когда вы цепляетесь для работы с одним и тем же объектом. Последний pipe(response) просто принимает входные данные от gzip, а не от raw. - person doup; 30.03.2014
comment
С 2018 года я могу связывать вызовы pipe () и получать ожидаемые данные. Это особенно полезно для чего-то вроде функции AWS Lambda - чтения из корзины как потока; труба к zlib gunzip; канал в доступный для записи поток, который сохраняет его в другое ведро / ключ. - person tsalaroth; 01.11.2018
comment
Этот ответ помог мне понять, что поток заканчивается при переходе к fs.createWriteStream, поэтому после этого момента он не может быть привязан к цепочке. - person lasec0203; 14.06.2019

Я обнаружил, что zlib возвращает читаемый поток, который позже может быть передан в несколько других потоков. Поэтому я сделал следующее, чтобы решить указанную выше проблему:

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));
person Eye    schedule 03.02.2013
comment
Голосовать против. Это избыточно, вообще не добавляет никакой новой информации и действительно помогает усугубить путаницу. - person Pooyan Khosravi; 06.09.2015
comment
Вы не можете направить записываемые потоки ни на что: github.com/ nodejs / readable-stream / blob / master / lib / для этого вам понадобится дуплекс или читаемый поток. - person inf3rno; 29.09.2015

вы можете использовать пакет "readable-stream-clone"

const fs = require("fs");
const ReadableStreamClone = require("readable-stream-clone");

const readStream = fs.createReadStream('text.txt');

const readStream1 = new ReadableStreamClone(readStream);
const readStream2 = new ReadableStreamClone(readStream);

const writeStream1 = fs.createWriteStream('sample1.txt');
const writeStream2 = fs.createWriteStream('sample2.txt');

readStream1.pipe(writeStream1)
readStream2.pipe(writeStream2)
person levansuper    schedule 21.05.2020