ArrayBuffer для base64 кодированной строки - PullRequest
154 голосов
/ 14 февраля 2012

Мне нужен эффективный (для чтения на нативном) способ преобразования ArrayBuffer в строку base64, которую необходимо использовать в составном сообщении.

Ответы [ 10 ]

183 голосов
/ 27 февраля 2012
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

75 голосов
/ 19 июля 2012

Это прекрасно работает для меня:

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

В ES6 синтаксис немного проще:

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

Как указано в комментариях, этот метод может привести кошибка во время выполнения в некоторых браузерах, когда ArrayBuffer большой.Точное ограничение размера зависит от реализации в любом случае.

30 голосов
/ 10 июля 2016

Существует еще один асинхронный способ использования 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"
27 голосов
/ 20 февраля 2017

Для тех, кто любит это коротко, вот другой, использующий Array.reduce, который не вызовет переполнение стека:

var base64 = btoa(
  new Uint8Array(arrayBuffer)
    .reduce((data, byte) => data + String.fromCharCode(byte), '')
);
11 голосов
/ 25 июля 2015

Моя рекомендация для этого - НЕ использовать нативные стратегии btoa, так как они неправильно кодируют все ArrayBuffer '*

, переписывают DOMs atob () и btoa ()

Поскольку строки DOMString представляют собой строки с 16-битным кодированием, в большинстве браузеров, вызывающих window.btoa для строки Unicode, возникает исключение «символ вне диапазона», если символ превышает диапазон 8.-битный ASCII-кодированный символ.

Хотя я никогда не сталкивался с этой точной ошибкой, я обнаружил, что многие из ArrayBuffer, которые я пытался кодировать, были закодированы неправильно.

Я бы использовал либо рекомендацию MDN, либо суть.

10 голосов
/ 09 августа 2016

Я использовал это и работает для меня.

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;
}
6 голосов
/ 26 июля 2017

Ниже приведены две простые функции для преобразования 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)));
}
1 голос
/ 08 декабря 2016

Вы можете получить нормальный массив из 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

}

Этот метод работает быстрее, поскольку в нем не выполняется никаких конкатенаций строк.

0 голосов
/ 07 февраля 2019

Со своей стороны, используя навигатор Chrome, мне пришлось использовать DataView () для чтения массива Buffer

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 голосов
/ 23 июля 2015
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 для распаковки архива из строки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...