在 Node.js 中将 Buffer 转换为 ReadableStream
Posted
技术标签:
【中文标题】在 Node.js 中将 Buffer 转换为 ReadableStream【英文标题】:Converting a Buffer into a ReadableStream in Node.js 【发布时间】:2012-10-25 04:38:12 【问题描述】:我对 Buffers 和 ReadableStreams 还很陌生,所以也许这是一个愚蠢的问题。我有一个将ReadableStream
作为输入的库,但我的输入只是一个base64 格式的图像。我可以像这样转换Buffer
中的数据:
var img = new Buffer(img_string, 'base64');
但我不知道如何将其转换为ReadableStream
或将我获得的Buffer
转换为ReadableStream
。
有没有办法做到这一点,还是我试图实现不可能的目标?
谢谢。
【问题讨论】:
【参考方案1】:您可以为此使用标准的 NodeJS 流 API - stream.Readable.from
const Readable = require('stream');
const stream = Readable.from(buffer);
注意:如果缓冲区包含二进制数据,请勿将缓冲区转换为字符串 (
buffer.toString()
)。这会导致二进制文件损坏。
【讨论】:
【参考方案2】:对于 nodejs 10.17.0 及更高版本:
const Readable = require('stream');
const stream = Readable.from(myBuffer.toString());
【讨论】:
你是最棒的❤️ 是的,这是最好的。我不认为 .toString() 是必要的。 对于导入: const Readable = require('stream') 这对图片文件有影响吗? 它适用于 OP 描述的情况,但如果缓冲区包含二进制数据.toString()
会损坏它【参考方案3】:
试试这个:
const Duplex = require('stream').Duplex; // core NodeJS API
function bufferToStream(buffer)
let stream = new Duplex();
stream.push(buffer);
stream.push(null);
return stream;
来源: 布赖恩·曼奇尼 -> http://derpturkey.com/buffer-to-stream-in-node/
【讨论】:
【参考方案4】:这是我的简单代码。
import Readable from 'stream';
const newStream = new Readable(
read()
this.push(someBuffer);
,
)
【讨论】:
【参考方案5】:您不需要为单个文件添加整个 npm 库。我将它重构为打字稿:
import Readable, ReadableOptions from "stream";
export class MultiStream extends Readable
_object: any;
constructor(object: any, options: ReadableOptions)
super(object instanceof Buffer || typeof object === "string" ? options : objectMode: true );
this._object = object;
_read = () =>
this.push(this._object);
this._object = null;
;
基于node-streamifier(如上所述的最佳选择)。
【讨论】:
【参考方案6】:这是一个使用 streamifier 模块的简单解决方案。
const streamifier = require('streamifier');
streamifier.createReadStream(new Buffer ([97, 98, 99])).pipe(process.stdout);
您可以使用字符串、缓冲区和对象作为其参数。
【讨论】:
另一个等效的替代方案是 tostream:const toStream = require('tostream'); toStream(new Buffer ([97, 98, 99])).pipe(process.stdout);
@YushinWashio 绝对。 Node 中有很多可用的模块。【参考方案7】:
这样的……
import Readable from 'stream'
const buffer = new Buffer(img_string, 'base64')
const readable = new Readable()
readable._read = () => // _read is required but you can noop it
readable.push(buffer)
readable.push(null)
readable.pipe(consumer) // consume the stream
在一般课程中,可读流的 _read
函数应该从底层源收集数据,push
它会逐步确保您不会在需要之前将大量源收集到内存中。
在这种情况下,虽然您已经在内存中拥有源代码,所以不需要_read
。
推送整个缓冲区只是将其包装在可读流 api 中。
【讨论】:
push()
_read()
方法中的缓冲区不是更正确吗? IE。 readable._read = () => readable.push(buffer); readable.push(null);
。不确定这是否重要,但允许流管理数据输入的时间似乎不太可能遇到意外行为。除此之外,这应该是公认的答案,因为它不依赖于 3rd 方模块。
一般来说,你是对的,但对于这个特定的用例,我不会在 read
方法中使用 push
。从概念上讲,我认为_read
应该保留用于从底层来源“收集”数据。在这种情况下,我们不仅有内存中的数据,而且不需要转换。因此,对于将数据包装在流中,我会这样做,但对于在流中转换或累积数据,该逻辑将发生在 _read
方法中。
你的底层来源是缓冲区;)
@FranckFreiburger 是的,但你不是从那个来源“收集”数据,它已经在内存中,你总是会一口气消耗掉它,你不会把它拉进去按需提供。【参考方案8】:
您可以像这样使用Node Stream Buffers 创建一个ReadableStream:
// Initialize stream
var myReadableStreamBuffer = new streamBuffers.ReadableStreamBuffer(
frequency: 10, // in milliseconds.
chunkSize: 2048 // in bytes.
);
// With a buffer
myReadableStreamBuffer.put(aBuffer);
// Or with a string
myReadableStreamBuffer.put("A String", "utf8");
频率不能为0,所以会引入一定的延迟。
【讨论】:
谢谢,虽然有点晚了。我不记得我是如何解决这个问题的,但这看起来是一个不错的解决方案。如果有人证实这一点,那就太好了。我记得我发现这次转化为零。 确认它有效 - 在查找如何将文件缓冲区转换为流时发现这一点。 如果您有处理文件的文件,您应该立即打开文件读取流:nodejs.org/api/fs.html#fs_fs_createreadstream_path_options 毫秒不是频率的度量——我想它们是指周期。 @UpTheCreek 我无法更改它,因为这是属性名称,单位是毫秒。【参考方案9】:Node Stream Buffer 显然是为测试而设计的;无法避免延迟使其成为生产使用的糟糕选择。
Gabriel Llamas 在这个答案中建议streamifier:How to wrap a buffer as a stream2 Readable stream?
【讨论】:
以上是关于在 Node.js 中将 Buffer 转换为 ReadableStream的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Node.js 中将 NTLM 凭据转换为 Kerberos 令牌