312 votes

ArrayBuffer vers une chaîne encodée en base64

J'ai besoin d'une méthode efficace (native) pour convertir un fichier ArrayBuffer à une chaîne de caractères base64 qui doit être utilisée dans un message multipartite.

329voto

mobz Points 331
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

Points de repère mis à jour : https://jsben.ch/wnaZC

16 votes

J'ai essayé l'implémentation non native du lien et il m'a fallu 1 minute et demie pour convertir un tampon d'une taille de 1M alors que le code de la boucle ci-dessus n'a pris que 1 seconde.

4 votes

J'aime la simplicité de cette approche, mais toute cette concaténation de chaînes peut être coûteuse. Il semble que l'on construise un tableau de caractères et de join() Les ajouter à la fin est nettement plus rapide sur Firefox, IE et Safari (mais beaucoup plus lent sur Chrome) : jsperf.com/tobase64-implementations

0 votes

J'utilise cette fonction pour la conversion de array buffer en base64 mais je n'arrive pas à récupérer le array buffer. J'ai écrit une fonction _base64ToArrayBuffer() ici : codeshare.io/PT4pb mais cela me donne une erreur comme : Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.

171voto

GOTO 0 Points 3049

Cela me convient parfaitement :

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

Dans ES6, la syntaxe est un peu plus simple :

const 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 l'élément ArrayBuffer est important. La taille limite exacte dépend en tout état de cause de l'implémentation.

58voto

gkunz Points 1171

Pour ceux qui préfèrent les versions courtes, en voici une autre qui utilise Array.reduce ce qui n'entraînera pas de débordement de pile :

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

44voto

cuixiping Points 644

Il existe une autre méthode asynchrone qui consiste à utiliser Blob et FileReader.

Je n'ai pas testé les performances. Mais c'est une autre façon de penser.

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"

36voto

Alex Points 230
var blob = new Blob([arrayBuffer])

var reader = new FileReader();
reader.onload = function(event){
   var base64 =   event.target.result
};

reader.readAsDataURL(blob);

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