Перетворення буфера в ReadableStream в Node.js


79

Я досить новачок у Buffers та ReadableStreams, тому, можливо, це дурне питання. У мене є бібліотека, яка приймає як вхідне значення a ReadableStream, але моє введення - це лише зображення формату base64. Я міг перетворити дані, які я маю, Bufferприблизно так:

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

Але я не уявляю, як перетворити його в a ReadableStreamабо перетворити Bufferотримане в a ReadableStream.

Чи є спосіб зробити це, чи я намагаюся досягти неможливого?

Дякую.

Відповіді:


31

Ви можете створити ReadableStream за допомогою буферів Node Stream приблизно так:

// 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, тому це вводить певну затримку.


Дякую, хоч і трохи пізно. Я не пам’ятаю, як я вирішив проблему, але це виглядає гарним рішенням. Якщо хтось підтвердить це, було б чудово. Я пам’ятаю, що знайшов НУЛЬ щодо цього перетворення.
Masiar

1
Підтверджуючи, що це працює - знайшов це при пошуку, як перетворити буфери файлів у потоки.
Джек Лоусон,

Якщо у вас є файли, з якими ви маєте справу, скоріше відразу відкрийте потік для читання файлів за допомогою цього: nodejs.org/api/fs.html#fs_fs_createreadstream_path_options
vanthome

2
Мілісекунди - це не вимірювання частоти - я гадаю, вони означають період.
UpTheCreek

@UpTheCreek Я не можу змінити це, оскільки це ім'я властивості, а одиниця - мілісекунди.
vanthome

63

щось на зразок цього...

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 читабельного потоку.


2
Чи не було б правильнішим push()буфер всередині _read()методу? Тобто readable._read = () => {readable.push(buffer); readable.push(null);}. Не впевнений, що це має значення, але надання дозволу потоку керувати часом, коли дані подаються, здається рідше натрапляє на несподівану поведінку. Крім цього, це має бути прийнятою відповіддю, оскільки вона не покладається на сторонні модулі.
broofa

1
Як правило, ви мали б рацію, але для цього конкретного випадку використання я б не pushпотрапив до readметоду. Концептуально, на мою думку, _readслід зарезервувати для "збору" даних із базового джерела. У цьому випадку ми не тільки маємо дані в пам'яті, але й перетворення не потрібно. Отже, для обгортання даних у потік я би це робив, але для перетворення або накопичення даних у потоці така логіка мала б місце в _readметоді.
Mr5o1

Вашим основним джерелом є буфер;)
Франк Фрайбургер,

@FranckFreiburger Так, але ви не "збираєте" дані з цього джерела, вони вже в пам'яті, і ви завжди збираєтеся споживати все за один раз, ви не втягуєте їх на вимогу.
Mr5o1

35

Node Stream Buffer , очевидно, розроблений для використання при тестуванні; неможливість уникнути затримки робить його невдалим вибором для виробничого використання.

Габріель Ламас пропонує стріамерифікатор у цій відповіді: Як обернути буфер як потік2 Читається потік?



5

Ось просте рішення з використанням модуля Streamifier .

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

В якості аргументів можна використовувати рядки, буфер та об’єкт.


1
Іншою рівноцінною альтернативою є течія :const toStream = require('tostream'); toStream(new Buffer ([97, 98, 99])).pipe(process.stdout);
Yushin Washio

@YushinWashio Безумовно. Багато модулів доступні в Node.
Shwetabh Shekhar

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 (найкращий варіант, як зазначено вище).


5

Це мій простий код для цього.

import { Readable } from 'stream';

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.