Как да насоча един четим поток към два записваеми потока едновременно в Node.js?

Целта е да:

  1. Създайте поток за четене на файл.
  2. Препратете го към gzip (zlib.createGzip())
  3. След това насочете потока за четене на изхода на zlib към:

    1) HTTP response обект

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

Сега мога да направя до 3.1:

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

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

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

... което работи добре, но също така трябва да запазя gzipped данните във файл, така че да не се налага да regzipвам всеки път и да мога директно да предавам gzipped данните като отговор.

И така, как да препратя един четим поток към два записваеми потока едновременно в 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