web-dev-qa-db-fra.com

ArrayBuffer to chaîne encodée en base64

J'ai besoin d'un moyen efficace (en lecture native) pour convertir un ArrayBuffer en une chaîne base64 devant être utilisée sur un article multipart. 

140
zaheer
function _arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}

mais les implémentations non natives sont plus rapides, par exemple. https://Gist.github.com/958841 voir http://jsperf.com/encoding-xhr-image-data/6

170
mobz

Cela fonctionne bien pour moi:

var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));

Dans ES6, la syntaxe est un peu plus simple:

let base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));

Comme indiqué dans les commentaires, cette méthode peut entraîner une erreur d'exécution dans certains navigateurs lorsque ArrayBuffer est volumineux. La limite de taille exacte dépend dans tous les cas de la mise en œuvre.

66
GOTO 0

Il existe une autre manière asynchrone d'utiliser Blob et FileReader.

Je n'ai pas testé la performance. Mais c'est une façon de penser différente.

function arrayBufferToBase64( buffer, callback ) {
    var blob = new Blob([buffer],{type:'application/octet-binary'});
    var reader = new FileReader();
    reader.onload = function(evt){
        var dataurl = evt.target.result;
        callback(dataurl.substr(dataurl.indexOf(',')+1));
    };
    reader.readAsDataURL(blob);
}

//example:
var buf = new Uint8Array([11,22,33]);
arrayBufferToBase64(buf, console.log.bind(console)); //"CxYh"
27
cuixiping

Pour ceux qui aiment ça, voici un autre en utilisant Array.reduce qui ne causera pas de débordement de pile:

var base64 = btoa(
  new Uint8Array(arrayBuffer)
    .reduce((data, byte) => data + String.fromCharCode(byte), '')
);
24
gkunz

Ma recommandation pour cela est de ne PAS utiliser les stratégies btoa natives, car elles ne codent pas correctement tous les ArrayBuffer

réécrit les DOM atob () et btoa ()

Comme DOMStrings sont des chaînes codées sur 16 bits, dans la plupart des navigateurs, appeler window.btoa sur une chaîne Unicode provoquera une exception Caractère hors plage si un caractère dépasse la plage d'un caractère codé ASCII sur 8 bits.

Bien que je n’aie jamais rencontré cette erreur exacte, j’ai constaté que beaucoup des ArrayBuffer que j’ai essayé de coder avaient mal codé.

Je voudrais soit utiliser la recommandation MDN ou Gist.

11
chemoish

Je l'ai utilisé et travaille pour moi.

function arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}



function base64ToArrayBuffer(base64) {
    var binary_string =  window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array( len );
    for (var i = 0; i < len; i++)        {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}
8
Elias Vargas

Vous trouverez ci-dessous deux fonctions simples permettant de convertir Uint8Array en Base64 String et vice-versa.

arrayToBase64String(a) {
    return btoa(String.fromCharCode(...a));
}

base64StringToArray(s) {
    let asciiString = atob(s);
    return new Uint8Array([...asciiString].map(char => char.charCodeAt(0)));
}
5
Steve Dixon

Vous pouvez dériver un tableau normal de ArrayBuffer en utilisant Array.prototype.slice. Utilisez une fonction comme Array.prototype.map pour convertir les octets en caractères et join ensemble pour former une chaîne.

function arrayBufferToBase64(ab){

    var dView = new Uint8Array(ab);   //Get a byte view        

    var arr = Array.prototype.slice.call(dView); //Create a normal array        

    var arr1 = arr.map(function(item){        
      return String.fromCharCode(item);    //Convert
    });

    return window.btoa(arr1.join(''));   //Form a string

}

Cette méthode est plus rapide car elle ne contient aucune concaténation de chaîne.

1
Charlie H

À mes côtés, en utilisant le navigateur Chrome, j'ai dû utiliser DataView () pour lire un arrayBuffer

function _arrayBufferToBase64( tabU8A ) {
var binary = '';
let lecteur_de_donnees = new DataView(tabU8A);
var len = lecteur_de_donnees.byteLength;
var chaine = '';
var pos1;
for (var i = 0; i < len; i++) {
    binary += String.fromCharCode( lecteur_de_donnees.getUint8( i ) );
}
chaine = window.btoa( binary )
return chaine;}
0
Louvet Jean