node.js: определить длину потока перед его передачей в конечный пункт назначения - PullRequest
0 голосов
/ 02 января 2019

Контекст этого вопроса заключается в том, что я беру буфер изображения, сжимаю его с pngquant , а затем передаю сжатый образ в ответ. Что-то вроде:

// https://www.npmjs.com/package/pngquant
const PngQuant = require('pngquant'); 

// start with base64-encoded png image data:
var base64data = '.......';

// then create buffer from this, as per:
//   https://stackoverflow.com/a/28440633/4070848
//   https://stackoverflow.com/a/52257416/4070848
var imgBuffer = Buffer.from(base64data, 'base64');

// set up pngquant...
const optionsArr = [ ..... ];
const myPngQuanter = new PngQuant(optionsArr);

// convert buffer into stream, as per:
//   https://stackoverflow.com/a/16044400/4070848
var bufferStream = new stream.PassThrough();
bufferStream.end(imgBuffer);

// pipe the image buffer (stream) through pngquant (to compress it) and then to res...
bufferStream.pipe(myPngQuanter).pipe(res);

Я хочу определить степень сжатия, достигнутую с помощью операции pngquant. Я могу легко найти начальный размер с:

const sizeBefore = imgBuffer.length;

Мне также нужен размер сжатого потока. Кроме того, эта информация должна быть доступна за до , когда поток передается по назначению res, потому что мне нужно добавить заголовок к res на основе статистики сжатия.

Чтобы получить sizeAfter Я попробовал модуль length-stream , где вы можете вставить слушателя в канал (между myPngQuanter и res), чтобы определить длину при прохождении через. Хотя кажется, что это работает для определения длины сжатого потока, добавление заголовков к res не происходит вовремя. Я также попробовал stream-length , но не могу заставить его работать вообще.

Любая помощь приветствуется.

1 Ответ

0 голосов
/ 02 января 2019

По своей природе потоки скважин не имеют информации о длине (поток может быть бесконечным, например, открытие /dev/random), поэтому самый простой вариант, который я вижу, это использование другого временного буфера.К сожалению, pngquant не имеет опций для работы с буферами, но вы ничего не можете с этим поделать, кроме использования совершенно другого пакета.

2-е редактирование, поскольку stream-буфер может не работать:

Существует пакет с именем stream-to-array, который позволяет легко реализовать преобразование потока в буфер.Согласно README , код должен быть изменен на:

const toArray = require('stream-to-array');
const util = require('util');
toArray(bufferStream.pipe(myPngQuanter))
.then(function (parts) {
  const buffers = parts
    .map(part => util.isBuffer(part) ? part : Buffer.from(part));
  const compressedBuffer = Buffer.concat(buffers);
  console.log(compressedBuffer.length); // here is the size of the compressed data
  res.write(compressedBuffer);
});

Или, альтернативно, на await, если вы оказались в контексте async:

const toArray = require('stream-to-array');
const util = require('util');
const parts = await toArray(bufferStream.pipe(myPngQuanter));
const buffers = parts.map(part => util.isBuffer(part) ? part : Buffer.from(part));
const compressedBuffer = Buffer.concat(buffers);
console.log(compressedBuffer.length); // here is the size of the compressed data
res.write(compressedBuffer);
...