node.js:在将流传输到最终目的地之前确定流的长度

标签 node.js node-streams pngquant

这个问题背后的上下文是我正在获取一个图像缓冲区,并使用 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 添加 header 统计数据。

为了获得sizeAfter,我尝试了 length-stream module ,您可以在其中将监听器插入管道(在 myPngQuanterres 之间)以确定其通过的长度。虽然这似乎确实可以确定压缩流的长度,但它并没有及时向 res 添加任何 header 。我也尝试过stream-length ,但根本无法让它工作。

感谢任何帮助。

最佳答案

流本质上并没有真正的长度信息(流可以是无限的,例如打开/dev/random),所以我能看到的最简单的选择是使用另一个临时缓冲区。不幸的是,pngquant 没有在缓冲区上操作的选项,但除了完全使用不同的包之外,您对此无能为力。

第二次编辑,因为流缓冲区可能不起作用:

有一个名为 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);

关于node.js:在将流传输到最终目的地之前确定流的长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54008318/

相关文章:

node.js - nginx 在每秒请求时变慢

node.js - 将数据管道传输到尚未准备好接收数据的可写流

javascript - 如何同时读取一个流并写入多个流?

Node.js如何通过背压处理快速生产者和慢速消费者

javascript - Electron ipc通讯

javascript - 动态窗口(盒子)和祝福中的元素(nodejs 文本 UI 库)

node.js - 使用 Node js将数据写入excel文件

php - pngquant PHP 示例不工作

node.js - 当我尝试在 cPanel 上安装 Laravel 时出现 pngquant 错误