Odpowiedzi:
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 );
}
ale implementacje nienatywne są szybsze, np. https://gist.github.com/958841 patrz http://jsperf.com/encoding-xhr-image-data/6
join()
ich na końcu jest znacznie szybsze w Firefox, IE i Safari (ale znacznie wolniej w Chrome): jsperf.com/tobase64-implementations
Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
To działa dobrze dla mnie:
var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
W ES6 składnia jest nieco prostsza:
let base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
Jak wskazano w komentarzach, ta metoda może powodować błąd czasu wykonywania w niektórych przeglądarkach, gdy ArrayBuffer
jest ona duża. Dokładny limit rozmiaru jest w każdym przypadku zależny od implementacji.
btoa([].reduce.call(new Uint8Array(bufferArray),function(p,c){return p+String.fromCharCode(c)},''))
btoa
jest bezpieczny dla znaków w zakresie kodu 0-255, ponieważ tak jest w tym przypadku (Pomyśl o 8 calach Uint8Array
).
Dla tych, którzy lubią to krótko, oto inne użycie, Array.reduce
które nie spowoduje przepełnienia stosu:
var base64 = btoa(
new Uint8Array(arrayBuffer)
.reduce((data, byte) => data + String.fromCharCode(byte), '')
);
<amount of Bytes in the buffer>
nowe ciągi.
btoa(new Uint8Array(arraybuffer).reduce((data,byte)=>(data.push(String.fromCharCode(byte)),data),[]).join(''))
?
Istnieje inny asynchroniczny sposób użycia obiektów Blob i FileReader.
Nie testowałem wydajności. Ale to inny sposób myślenia.
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]
zamiast dataurl.substr(dataurl.indexOf(',')+1)
.
readAsDataURL
teoretycznie może zwrócić procentowo zakodowane daneURI (i wygląda na to, że tak naprawdę jest w jsdom )
split
lepszy niż substring
?
Użyłem tego i działa dla mnie.
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;
}
Zalecam, aby NIE używać natywnych btoa
strategii - ponieważ nie kodują one poprawnie wszystkich ArrayBuffer
…
przepisz DOMs atob () i btoa ()
Ponieważ ciągi DOMS są ciągami zakodowanymi w 16 bitach, w większości przeglądarek wywołanie metody window.btoa w ciągu znaków Unicode spowoduje wyjątek Znak poza zakresem, jeśli znak przekroczy zakres 8-bitowego znaku zakodowanego w ASCII.
Chociaż nigdy nie spotkałem się z tym dokładnym błędem, odkryłem, że wiele z nich ArrayBuffer
, które próbowałem zakodować, zostało zakodowanych nieprawidłowo.
Użyłbym rekomendacji MDN lub gist.
btoa
nie działa na String, ale OP pyta ArrayBuffer
.
var blob = new Blob([arrayBuffer])
var reader = new FileReader();
reader.onload = function(event){
var base64 = event.target.result
};
reader.readAsDataURL(blob);
Poniżej znajdują się 2 proste funkcje do konwersji Uint8Array na Base64 String iz powrotem
arrayToBase64String(a) {
return btoa(String.fromCharCode(...a));
}
base64StringToArray(s) {
let asciiString = atob(s);
return new Uint8Array([...asciiString].map(char => char.charCodeAt(0)));
}
function
słowo kluczowe i powinno działać w nowoczesnej przeglądarce.
Możesz uzyskać normalną tablicę ArrayBuffer
za pomocą Array.prototype.slice
. Użyj funkcji takiej jak Array.prototype.map
konwersja bajtów na znaki i join
razem na ciąg znaków.
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
}
Ta metoda jest szybsza, ponieważ nie ma w niej żadnych konkatenacji łańcuchów.
OP nie określił Środowiska Działającego, ale jeśli używasz Node.JS, istnieje bardzo prosty sposób na zrobienie czegoś takiego.
Zgodnie z oficjalnymi dokumentami 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');
Ponadto, jeśli pracujesz na przykład w Angular, klasa bufora zostanie również udostępniona w środowisku przeglądarki.
Javascript
. Zaktualizowałem więc odpowiedź, aby była bardziej zwięzła. Myślę, że to ważna odpowiedź, ponieważ szukałem, jak to zrobić i nie mogłem znaleźć najlepszej odpowiedzi na problem.
Z mojej strony, korzystając z nawigatora Chrome, musiałem użyć DataView (), aby odczytać 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("");
}
Jest to lepsze, jeśli używasz JSZip do rozpakowywania archiwum z ciągu