webentwicklung-frage-antwort-db.com.de

So wechseln Sie von Blob zu ArrayBuffer

Ich habe Blobs studiert und festgestellt, dass Sie mit einem ArrayBuffer dies wie folgt problemlos in einen Blob konvertieren können:

var dataView = new DataView(arrayBuffer);
var blob = new Blob([dataView], { type: mimeString });

Die Frage, die ich jetzt habe, ist, ist es möglich, von einem Blob zu einem ArrayBuffer zu wechseln?

97

Die API newResponse kann Daten aus einem (unveränderlichen) Blob dekodieren. Dies ist die Core-API, die von Fetch API verwendet wird.

var blob = GetABlobSomehow();
var arrayBuffer = null;

/* Use the await keyword to wait for the Promise to resolve */
arrayBuffer = await new Response(blob).arrayBuffer();   //: ArrayBuffer

alternativ können Sie dies verwenden ( synchron):

new Response(blob).arrayBuffer()
.then(/* callback function */);

im Backend werden die Oktette aus dem Blob an das von Promise zurückgegebene ArrayBuffer gestreamt.


Hinweis: Dieses [~ # ~] api [~ # ~] wird von älteren Browsern daher nicht unterstützt Schauen Sie zur Sicherheit in die Browser-Kompatibilitätstabelle .

13
nullptr

Sie können FileReader verwenden, um Blob als ArrayBuffer zu lesen.

Hier ist ein kurzes Beispiel:

var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) {
    arrayBuffer = event.target.result;
};
fileReader.readAsArrayBuffer(blob);

Hier ist ein längeres Beispiel:

// ArrayBuffer -> Blob
var uint8Array  = new Uint8Array([1, 2, 3]);
var arrayBuffer = uint8Array.buffer;
var blob        = new Blob([arrayBuffer]);

// Blob -> ArrayBuffer
var uint8ArrayNew  = null;
var arrayBufferNew = null;
var fileReader     = new FileReader();
fileReader.onload  = function(event) {
    arrayBufferNew = event.target.result;
    uint8ArrayNew  = new Uint8Array(arrayBufferNew);

    // warn if read values are not the same as the original values
    // arrayEqual from: http://stackoverflow.com/questions/3115982/how-to-check-javascript-array-equals
    function arrayEqual(a, b) { return !(a<b || b<a); };
    if (arrayBufferNew.byteLength !== arrayBuffer.byteLength) // should be 3
        console.warn("ArrayBuffer byteLength does not match");
    if (arrayEqual(uint8ArrayNew, uint8Array) !== true) // should be [1,2,3]
        console.warn("Uint8Array does not match");
};
fileReader.readAsArrayBuffer(blob);
fileReader.result; // also accessible this way once the blob has been read

Dies wurde in der Konsole von Chrome 27—69, Firefox 20—60 und Safari 6—11 getestet.

Hier ist auch eine Live-Demonstration, mit der Sie spielen können: https://jsfiddle.net/potatosalad/FbaM6/

Update 23.06.2018: Danke an Klaus Klein für den Tipp zu event.target.result gegen this.result

Referenz:

133
potatosalad

Nur um die Antwort von Herrn @potatosalad zu ergänzen.

Sie müssen nicht unbedingt auf die Funktion scope zugreifen, um das Ergebnis für den onload - Rückruf zu erhalten. Sie können beim event Folgendes tun Parameter:

var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) {
    arrayBuffer = event.target.result;
};
fileReader.readAsArrayBuffer(blob);

Warum ist das besser? Denn dann können wir die Pfeilfunktion verwenden, ohne den Kontext zu verlieren

var fileReader = new FileReader();
fileReader.onload = (event) => {
    this.externalScopeVariable = event.target.result;
};
fileReader.readAsArrayBuffer(blob);
15
Klaus Klein

Oder Sie können die Abruf-API verwenden

fetch(URL.createObjectURL(myBlob)).then(res => res.arrayBuffer())

Ich weiß nicht, wie hoch der Leistungsunterschied ist, und dies wird auch in DevTools auf der Registerkarte "Netzwerk" angezeigt.

13
Arlen Beiler