【问题标题】:Converting a Buffer into a ReadableStream in Node.js在 Node.js 中将 Buffer 转换为 ReadableStream
【发布时间】:2023-03-21 13:50:01
【问题描述】:

我对 Buffers 和 ReadableStreams 还很陌生,所以也许这是一个愚蠢的问题。我有一个将ReadableStream 作为输入的库,但我的输入只是一个base64 格式的图像。我可以像这样转换Buffer 中的数据:

var img = new Buffer(img_string, 'base64');

但我不知道如何将其转换为ReadableStream 或将我获得的Buffer 转换为ReadableStream

有没有办法做到这一点,还是我试图实现不可能的目标?

谢谢。

【问题讨论】:

    标签: javascript node.js stream buffer


    【解决方案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 在这个答案中建议streamifierHow to wrap a buffer as a stream2 Readable stream?

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-06-16
              • 2012-01-10
              • 2013-07-19
              • 1970-01-01
              • 2020-08-25
              • 2020-09-10
              • 2018-01-23
              相关资源
              最近更新 更多