141 votes

Comment passer de Blob à ArrayBuffer ?

En étudiant les blobs, j'ai remarqué que lorsque vous avez un ArrayBuffer, vous pouvez facilement le convertir en un blob comme suit :

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

La question que je me pose maintenant est la suivante : est-il possible de passer d'un Blob à un ArrayBuffer ?

4 votes

Les blobs ne sont pas au format JS natif. Ils sont comme des références à des données, mais pas les données réelles. Les données d'un Blob ne peut pas être lu directement, mais cela peut être fait avec certaines API.

156voto

potatosalad Points 4004

Vous pouvez utiliser FileReader pour lire le Blob comme un ArrayBuffer .

Voici un petit exemple :

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

Voici un exemple plus long :

// 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

Ceci a été testé dans la console de Chrome 27-69, Firefox 20-60, et Safari 6-11.

Voici également une démonstration en direct avec laquelle vous pouvez jouer : https://jsfiddle.net/potatosalad/FbaM6/

Mise à jour 2018-06-23 : Merci à Klaus Klein pour le tuyau sur event.target.result contre this.result

Référence :

30 votes

Cela ne semble-t-il pas être beaucoup de code pour quelque chose qui devrait être simple ?

4 votes

@HenleyChiu J'ai modifié la réponse pour inclure une version courte du code. L'exemple plus long est censé être entièrement autonome (il montre comment créer le ArrayBuffer, le Blob et inversement). Je n'ai pas été en mesure de trouver un moyen synchrone de lire un Blob sans utiliser une fonction Travailleur du Web y FileReaderSync .

2 votes

Certaines personnes veulent vraiment prouver que l'enfer du rappel existe. Cela a du sens pour les GROS blobs, mais pour les cas d'utilisation normaux, JavaScript devrait fournir une méthode de synchronisation.

69voto

bsound Points 722

Le site Response consomme un fichier (immuable) Blob à partir duquel les données peuvent être récupérées de plusieurs façons. Le site OP a seulement demandé ArrayBuffer et en voici une démonstration.

var blob = GetABlobSomehow();

// NOTE: you will need to wrap this up in a async block first.
/* Use the await keyword to wait for the Promise to resolve */
await new Response(blob).arrayBuffer();   //=> <ArrayBuffer>

Vous pouvez aussi utiliser ceci :

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

Note : Ce site API n'est pas compatible avec les anciennes versions ( anciennement ), alors jetez un coup d'œil à la Tableau de compatibilité des navigateurs pour être sûr ;)

4 votes

Astuce intelligente et à ne pas confondre avec Blob.arrayBuffer() qui a en fait une compatibilité assez faible, même en 2020, caniuse.com/#feat=mdn-api_blob_arraybuffer o developer.mozilla.org/fr/US/docs/Web/API/Blob/arrayBuffer

0 votes

Quelle est la performance de ceci ? Copie-t-elle les données dans le Blob ou renvoie-t-elle simplement une vue de celles-ci ?

0 votes

@GaryO Je ne l'ai pas testé, je suppose qu'il copie le blob et renvoie une vue sur celui-ci.

22voto

Arlen Beiler Points 1619

Ou vous pouvez utiliser l'API de récupération

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

Je ne sais pas quelle est la différence de performance, et cela apparaîtra sur votre onglet réseau dans DevTools aussi.

26 votes

Ou juste new Response(blob).arrayBuffer()

5 votes

Ou await blob.arrayBuffer() qui bénéficie désormais d'un bon soutien : developer.mozilla.org/fr/US/docs/Web/API/Blob/

18voto

Klaus Klein Points 315

Juste pour compléter la réponse de M. @potatosalad.

Vous n'avez pas réellement besoin d'accéder à la fonction portée pour obtenir le résultat sur le onload vous pouvez librement faire ce qui suit sur l'objet événement paramètre :

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

Pourquoi ceci est mieux ? Parce que nous pouvons alors utiliser la fonction flèche sans perdre le contexte.

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

11voto

Ramtin Points 983

Il s'agit d'une méthode asynchrone qui vérifie d'abord la disponibilité de l'option arrayBuffer méthode. Cette fonction est rétrocompatible et évolutive.

async function blobToArrayBuffer(blob) {
    if ('arrayBuffer' in blob) return await blob.arrayBuffer();

    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result);
        reader.onerror = () => reject;
        reader.readAsArrayBuffer(blob);
    });
}

0 votes

Il semble que ce soit une mauvaise réponse puisque la valeur de retour de l'option reader.onerror ne peut pas être une fonction. Il devrait donc être comme le suivant. reader.onerror = (e) => reject(e) o reader.onerror = reject

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X