Konvertieren eines Puffers in einen ReadableStream in Node.js.


77

Ich bin ziemlich neu in Buffers und ReadableStreams, also ist das vielleicht eine dumme Frage. Ich habe eine Bibliothek, die als Eingabe a verwendet ReadableStream, aber meine Eingabe ist nur ein Bild im Base64-Format. Ich könnte die Daten, die ich habe, Bufferso konvertieren :

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

Aber ich habe keine Ahnung, wie ich es in ein ReadableStreamkonvertieren oder das, was Bufferich erhalten habe, in ein konvertieren soll ReadableStream.

Gibt es eine Möglichkeit, dies zu tun, oder versuche ich, das Unmögliche zu erreichen?

Vielen Dank.

Antworten:


29

Sie können einen ReadableStream mit Node Stream Buffers wie folgt erstellen :

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

Die Frequenz kann nicht 0 sein, daher führt dies zu einer gewissen Verzögerung.


Danke, wenn auch etwas spät. Ich erinnere mich nicht, wie ich das Problem gelöst habe, aber das sieht nach einer guten Lösung aus. Wenn jemand dies bestätigt, wäre es großartig. Ich erinnere mich, dass ich bei dieser Konvertierung NULL gefunden habe.
Masiar

1
Bestätigen, dass es funktioniert - Dies wurde festgestellt, als nachgeschlagen wurde, wie Dateipuffer in Streams umgewandelt werden.
Jack Lawson

Wenn Sie Dateien haben, mit denen Sie sich befassen, sollten Sie lieber sofort einen Datei- Lesestream
öffnen

2
Millisekunden sind keine Frequenzmessung - ich nehme an, sie bedeuten Periode.
UpTheCreek

@UpTheCreek Ich kann es nicht ändern, da dies der Eigenschaftsname ist und die Einheit Millisekunden ist.
Vanthome

61

etwas wie das...

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

Im Allgemeinen _readsollte die Funktion eines lesbaren Streams Daten von der zugrunde liegenden Quelle erfassen und pushschrittweise sicherstellen, dass Sie keine große Quelle in den Speicher einspeisen, bevor sie benötigt wird.

In diesem Fall ist die Quelle zwar bereits im Speicher, dies _readist jedoch nicht erforderlich.

Durch Drücken des gesamten Puffers wird dieser einfach in die lesbare Stream-API eingeschlossen.


2
Wäre es nicht korrekter für push()den Puffer innerhalb der _read()Methode? Dh readable._read = () => {readable.push(buffer); readable.push(null);}. Ich bin mir nicht sicher, ob es wichtig ist, aber es scheint weniger wahrscheinlich zu sein, dass der Stream das Timing der Dateneingabe verwaltet. Davon abgesehen sollte dies die akzeptierte Antwort sein, da sie nicht auf Modulen von Drittanbietern basiert.
Broofa

1
Im Allgemeinen hätten Sie Recht, aber für diesen speziellen Anwendungsfall würde ich mich nicht mit pushder readMethode befassen. Konzeptionell denke ich, _readsollte für das "Ernten" von Daten aus einer zugrunde liegenden Quelle reserviert werden. In diesem Fall haben wir nicht nur die Daten im Speicher, sondern es ist auch keine Konvertierung erforderlich. Um Daten in einen Stream zu verpacken, würde ich das so machen, aber um Daten in einen Stream zu konvertieren oder zu akkumulieren, würde diese Logik in der _readMethode passieren .
Mr5o1

Ihre zugrunde liegende Quelle ist der Puffer;)
Franck Freiburger

@FranckFreiburger Ja, aber Sie "ernten" keine Daten aus dieser Quelle, sie befinden sich bereits im Speicher und Sie werden immer alles auf einmal verbrauchen, Sie ziehen sie nicht bei Bedarf ein.
Mr5o1


24

Für Knoten 10.17.0 und höher:

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

du bist der Beste ❤️
Alesso

3
Ja das ist das Beste. Ich denke jedoch nicht, dass .toString () notwendig ist.
Dmitry Minkovsky

Für die Importe: const {Readable} = require ('stream')
Philipp Claßen

5

Hier ist eine einfache Lösung mit dem Streamifier- Modul.

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

Sie können Strings, Buffer und Object als Argumente verwenden.


1
Eine andere äquivalente Alternative ist tostream :const toStream = require('tostream'); toStream(new Buffer ([97, 98, 99])).pipe(process.stdout);
Yushin Washio

@ YushinWashio Auf jeden Fall. In Node sind viele Module verfügbar.
Shwetabh Shekhar

5

Sie müssen nicht eine ganze npm lib für eine einzelne Datei hinzufügen. Ich habe es in Typoskript umgestaltet:

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

basierend auf Node-Streamifier (die beste Option wie oben erwähnt).


5

Dies ist mein einfacher Code dafür.

import { Readable } from 'stream';

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.