Передача потока, только если дайджест проходит - PullRequest
0 голосов
/ 28 мая 2018

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

function GetFile(req,res) {
    ...
    }).then(() => {
        var p1 = new Promise(function(resolve,reject) {
            digester = digestStream("md5", "hex", function(md5,len) {
                // compare md5 and length against expected values
                // what do i do if they don't match?
                resolve()
            }
        }
        infile.pipe(decrypter).pipe(digester).pipe(res)
        return p1
    }).then(() => {
    ...
}

Проблема в том, что, как только я передаю вывод в res, он передает его независимо от того, проходит ли дайджест.Но если я не направлю вывод метантенка на что-либо, то ничего не произойдет - я думаю, что с правого конца нет давления для перемещения данных.

Я мог бы просто дважды запустить конвейер дешифрованияи на самом деле это было то, что было сделано ранее, но я пытаюсь ускорить процесс, чтобы все происходило только один раз.Одна из моих идей заключалась в том, чтобы направить выходные данные метантенка в буфер, и, если дайджест совпадает, отправьте буфер в res.Для этого потребуется память, пропорциональная размеру файла, что в большинстве случаев не так уж и плохо.Тем не менее, я не мог найти много о том, как .pipe() непосредственно в буфер.Самым близким, что я смог найти, был модуль bl , однако в разделе, в котором он демонстрирует конвейерную связь с функцией, которая собирает данные, упоминается следующее предостережение:

Примечаниечто при использовании метода обратного вызова, подобного этому, результирующий параметр данных является объединением всех объектов Buffer в списке.Если вы хотите избежать издержек этой конкатенации (в случаях чрезмерного сознания производительности), тогда избегайте метода обратного вызова и просто вместо этого слушайте 'end', как стандартный поток.

I'mнедостаточно знаком с bl, чтобы понять, что это на самом деле означает в отношении его эффективности.В частности, я не понимаю, почему речь идет о конкатенации буферных объектов - почему, например, нужно объединить более одного буферного объекта?).Я не уверен, как я могу последовать его совету и все еще иметь простую трубку.

1 Ответ

0 голосов
/ 28 мая 2018

Модуль bl собирается собирать буферы, когда он передается по конвейеру.Сколько буферов зависит от того, что делает входной поток.Если вы не хотите объединять их вместе, сохраните их в BufferList, а если хеш пройдет, затем перенаправьте BufferList на ваш вывод.

Что-то вроде этого работает для меня:

function GetFile(req,res) {
    ...
    var bl
    }).then(() => {
        var p1 = new Promise(function(resolve,reject) {
            digester = digestStream("md5", "hex", function(md5,len) {
                if (md5 != expectedmd5) throw "bad md5"
                if (len != expectedlen) throw "bad length"
                resolve()
            }
        }
        bl = new BufferList()
        infile.pipe(decrypter).pipe(digester).pipe(bl)
        return p1
    }).then(() => {
        bl.pipe(res)
    ...
}
...