Réponses:
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
join()
leur ing à la fin est beaucoup plus rapide sur Firefox, IE et Safari (mais beaucoup plus lent sur Chrome): jsperf.com/tobase64-implementations
Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
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 lorsqu'elle ArrayBuffer
est volumineuse. La taille exacte dépend de l'implémentation dans tous les cas.
btoa([].reduce.call(new Uint8Array(bufferArray),function(p,c){return p+String.fromCharCode(c)},''))
btoa
est sans danger pour les caractères dans la plage de code 0-255, comme c'est le cas ici (pensez au 8 pouces Uint8Array
).
Pour ceux qui l'aiment court, voici une autre utilisation Array.reduce
qui ne causera pas de débordement de pile:
var base64 = btoa(
new Uint8Array(arrayBuffer)
.reduce((data, byte) => data + String.fromCharCode(byte), '')
);
<amount of Bytes in the buffer>
nouvelles chaînes.
btoa(new Uint8Array(arraybuffer).reduce((data,byte)=>(data.push(String.fromCharCode(byte)),data),[]).join(''))
?
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"
dataurl.split(',', 2)[1]
au lieu de dataurl.substr(dataurl.indexOf(',')+1)
.
readAsDataURL
pourrait théoriquement renvoyer un pourcentage codé dataURI (et il semble que ce soit effectivement le cas dans jsdom )
split
mieux que substring
?
J'ai utilisé cela 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;
}
Ma recommandation est de ne PAS utiliser de btoa
stratégies natives, car elles ne codent pas correctement toutes ArrayBuffer
…
réécrire les DOM atob () et btoa ()
Étant donné que DOMStrings sont des chaînes codées sur 16 bits, dans la plupart des navigateurs appelant window.btoa sur une chaîne Unicode provoquera une exception de caractère hors plage si un caractère dépasse la plage d'un caractère codé en ASCII 8 bits.
Bien que je n'aie jamais rencontré cette erreur exacte, j'ai constaté que la plupart des codes que ArrayBuffer
j'ai essayé de coder ne sont pas codés correctement.
J'utiliserais soit la recommandation MDN ou l'essentiel.
btoa
ne fonctionne pas sur String, mais OP demande ArrayBuffer
.
var blob = new Blob([arrayBuffer])
var reader = new FileReader();
reader.onload = function(event){
var base64 = event.target.result
};
reader.readAsDataURL(blob);
Voici 2 fonctions simples pour convertir Uint8Array en chaîne Base64 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)));
}
function
mot - clé et cela devrait fonctionner dans un navigateur moderne.
Vous pouvez dériver un tableau normal de à l' ArrayBuffer
aide de Array.prototype.slice
. Utilisez une fonction telle que Array.prototype.map
convertir les octets en caractères et join
les convertir ensemble en 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 il n'y a aucune concaténation de chaînes en cours d'exécution.
L'OP n'a pas spécifié l'environnement d'exécution, mais si vous utilisez Node.JS, il existe un moyen très simple de le faire.
Accord avec les documents officiels Node.JS https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
// This step is only necessary if you don't already have a Buffer Object
const buffer = Buffer.from(yourArrayBuffer);
const base64String = buffer.toString('base64');
De plus, si vous utilisez sous Angular par exemple, la classe de tampon sera également disponible dans un environnement de navigateur.
Javascript
. J'ai donc mis à jour ma réponse pour la rendre plus concise. Je pense que c'est une réponse importante parce que je cherchais comment faire et je n'ai pas pu trouver la meilleure réponse au problème.
À 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;}
function _arrayBufferToBase64(uarr) {
var strings = [], chunksize = 0xffff;
var len = uarr.length;
for (var i = 0; i * chunksize < len; i++){
strings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize)));
}
return strings.join("");
}
C'est mieux si vous utilisez JSZip pour décompresser l'archive de la chaîne