Відповіді:
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 );
}
але неноші реалізації швидші, наприклад https://gist.github.com/958841 див. http://jsperf.com/encoding-xhr-image-data/6
join()
їхнє завершення значно швидше на Firefox, IE та Safari (але набагато повільніше на Chrome): jsperf.com/tobase64-implementations
Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
Це добре для мене:
var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
У ES6 синтаксис трохи простіший:
let base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
Як зазначалося в коментарях, цей метод може призвести до помилки під час виконання у деяких браузерах, коли величина ArrayBuffer
є великою. Точний обмеження розміру залежить від реалізації в будь-якому випадку.
btoa([].reduce.call(new Uint8Array(bufferArray),function(p,c){return p+String.fromCharCode(c)},''))
btoa
безпечний для символів у діапазоні коду 0-255, оскільки це так (подумайте про 8 дюймів Uint8Array
).
Для тих, кому це подобається короткий, ось ще один, за допомогою Array.reduce
якого не викличе переповнення стека:
var base64 = btoa(
new Uint8Array(arrayBuffer)
.reduce((data, byte) => data + String.fromCharCode(byte), '')
);
<amount of Bytes in the buffer>
нові рядки.
btoa(new Uint8Array(arraybuffer).reduce((data,byte)=>(data.push(String.fromCharCode(byte)),data),[]).join(''))
?
Існує ще один асинхронний спосіб використання Blob і FileReader.
Я не перевіряв продуктивність. Але це інший спосіб мислення.
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]
замість dataurl.substr(dataurl.indexOf(',')+1)
.
readAsDataURL
теоретично міг би повернути відсоток закодованих данихURI (І, здається, це справді так у jsdom )
split
б краще, ніж substring
?
Я використав це і працює на мене.
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;
}
Моя рекомендація щодо цього НЕ використовувати нативну btoa
стратегію, оскільки вони неправильно кодують всіArrayBuffer
"...
переписати DOMs atob () та btoa ()
Оскільки DOMStrings - це 16-бітові кодовані рядки, то в більшості браузерів, що викликають window.btoa в рядку Unicode, буде викликати виняток "Символ поза діапазоном", якщо символ перевищує діапазон 8-бітового символу, кодованого ASCII.
Хоча я ніколи не стикався з цією точною помилкою, я виявив, що багато хто з них ArrayBuffer
, які я намагався кодувати, кодували неправильно.
Я б або застосував рекомендацію MDN, або суть.
btoa
не працює на String, але ОП запитує ArrayBuffer
.
var blob = new Blob([arrayBuffer])
var reader = new FileReader();
reader.onload = function(event){
var base64 = event.target.result
};
reader.readAsDataURL(blob);
Нижче наведено дві прості функції для перетворення Uint8Array в Base64 String та назад
arrayToBase64String(a) {
return btoa(String.fromCharCode(...a));
}
base64StringToArray(s) {
let asciiString = atob(s);
return new Uint8Array([...asciiString].map(char => char.charCodeAt(0)));
}
function
ключове слово, і воно повинно працювати в сучасному браузері.
Ви можете отримати звичайний масив з ArrayBuffer
, використовуючи Array.prototype.slice
. Використовуйте таку функцію, як Array.prototype.map
перетворення байтів у символи та join
їх разом у рядок формату.
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
}
Цей метод швидший, оскільки в ньому не працює жодних струнних конкатенацій.
ОП не вказав Running Enviroment, але якщо ви використовуєте Node.JS, існує дуже простий спосіб зробити таке.
Погоджуються з офіційними документами 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');
Крім того, якщо, наприклад, ви працюєте під Angular, клас буфера також буде доступний у середовищі браузера.
Javascript
. Тому я оновив свою відповідь, щоб зробити її більш стислою. Я думаю, що це важлива відповідь, тому що я шукав, як це зробити, і не міг дійти до найкращої відповіді на проблему.
З мого боку, за допомогою навігатора Chrome, мені довелося використовувати DataView () для читання 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("");
}
Це краще, якщо ви використовуєте JSZip для розпакування архіву з рядка