Chuyển đổi Buffer thành ReadableStream trong Node.js


79

Tôi khá mới với Buffers và ReadableStreams, vì vậy có thể đây là một câu hỏi ngu ngốc. Tôi có một thư viện làm đầu vào a ReadableStream, nhưng đầu vào của tôi chỉ là hình ảnh định dạng base64. Tôi có thể chuyển đổi dữ liệu tôi có theo cách Buffernhư vậy:

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

Nhưng tôi không biết làm thế nào để chuyển đổi nó thành a ReadableStreamhoặc chuyển đổi Buffertôi thu được thành a ReadableStream.

Có cách nào để làm điều này hay tôi đang cố gắng đạt được điều không thể?

Cảm ơn.

Câu trả lời:


31

Bạn có thể tạo luồng có thể đọc bằng cách sử dụng Bộ đệm luồng Node như sau:

// 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");

Tần số không thể là 0 vì vậy điều này sẽ tạo ra một độ trễ nhất định.


Cảm ơn, mặc dù hơi muộn. Tôi không nhớ mình đã giải quyết vấn đề như thế nào, nhưng đây có vẻ là một giải pháp tốt. Nếu ai đó xác nhận điều này thì thật tuyệt. Tôi nhớ đã tìm thấy KHÔNG về chuyển đổi này.
Masiar

1
Xác nhận rằng nó hoạt động - tìm thấy điều này khi tìm kiếm cách biến bộ đệm tệp thành luồng.
Jack Lawson

Nếu bạn có các tập tin bạn đối phó với các tập tin bạn thay vì phải mở một tập tin đọc dòng ngay lập tức với điều này: nodejs.org/api/fs.html#fs_fs_createreadstream_path_options
vanthome

2
Mili giây không phải là phép đo tần số - tôi cho rằng chúng có nghĩa là chu kỳ.
UpTheCreek

@UpTheCreek Tôi không thể thay đổi nó vì đây là tên thuộc tính và đơn vị là mili giây.
vanthome

63

một cái gì đó như thế này ...

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

Nói chung, _readchức năng của luồng có thể đọc được sẽ thu thập dữ liệu từ nguồn bên dưới và pushnó dần dần đảm bảo bạn không thu thập một nguồn khổng lồ vào bộ nhớ trước khi cần.

Trong trường hợp này, mặc dù bạn đã có nguồn trong bộ nhớ, nhưng _readkhông bắt buộc.

Việc đẩy toàn bộ bộ đệm chỉ bao bọc nó trong api luồng có thể đọc được.


2
Nó sẽ không đúng hơn với push()bộ đệm bên trong _read()phương thức? Tức là readable._read = () => {readable.push(buffer); readable.push(null);}. Không chắc điều đó có quan trọng không, nhưng cho phép luồng quản lý thời gian khi dữ liệu được đưa vào dường như ít có khả năng xảy ra hành vi không mong muốn. Ngoài ra, đây phải là câu trả lời được chấp nhận, vì nó không dựa trên các mô-đun của bên thứ ba.
broofa

1
Nói chung, bạn muốn thể đúng, nhưng đối với trường hợp sử dụng cụ thể này tôi sẽ không pushbên trong readphương pháp. Về mặt khái niệm, tôi nghĩ _readnên dành riêng cho việc "thu thập" dữ liệu từ một nguồn cơ bản. Trong trường hợp này, chúng tôi không chỉ có dữ liệu trong bộ nhớ mà không cần chuyển đổi. Vì vậy, để gói dữ liệu trong một luồng, đây là cách tôi sẽ làm, nhưng để chuyển đổi hoặc tích lũy dữ liệu trong một luồng, logic đó sẽ xảy ra trong _readphương thức.
Mr5o1

Nguồn cơ bản của bạn là bộ đệm;)
Franck Freiburger

@FranckFreiburger Có, nhưng bạn không "thu thập" dữ liệu từ nguồn đó, nó đã nằm trong bộ nhớ và bạn sẽ luôn sử dụng hết dữ liệu trong một lần, bạn không lấy nó theo yêu cầu.
Mr5o1


32

Đối với nodejs 10.17.0 trở lên:

const stream = Readable.from(myBuffer.toString());

bạn là người giỏi nhất ❤️
Alesso

7
Vâng, đây là điều tốt nhất. Tôi không nghĩ .toString () là cần thiết.
Dmitry Minkovsky

3
Đối với nhập: const {Readable} =
request

5

Đây là một giải pháp đơn giản sử dụng streamifier module.

const streamifier = require('streamifier');
streamifier.createReadStream(new Buffer ([97, 98, 99])).pipe(process.stdout);

Bạn có thể sử dụng Chuỗi, Bộ đệm và Đối tượng làm đối số của nó.


1
Một thay thế tương đương khác là tostream :const toStream = require('tostream'); toStream(new Buffer ([97, 98, 99])).pipe(process.stdout);
Yushin Washio

@YushinWashio Chắc chắn. Rất nhiều mô-đun có sẵn trong Node.
Shwetabh Shekhar

5

Bạn không cần phải thêm toàn bộ npm lib cho một tệp. tôi đã cấu trúc lại nó thành kiểu chữ:

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;
  };
}

dựa trên node-streamifier (tùy chọn tốt nhất như đã nói ở trên).


5

Đây là mã đơn giản của tôi cho việc này.

import { Readable } from 'stream';

const newStream = new Readable({
                    read() {
                      this.push(someBuffer);
                    },
                  })

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.