关于javascript:ArrayBuffer到base64编码的字符串

ArrayBuffer to base64 encoded string

我需要一种有效的(本机读)方法来将arrayBuffer转换为base64字符串,该字符串需要在多部分日志中使用。


1
2
3
4
5
6
7
8
9
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://jspef.com/encoding-xhr-image-data/6


这对我来说很好:

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

在ES6中,语法稍微简单一点:

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

正如注释中指出的,当arrayBuffer很大时,此方法可能会在某些浏览器中导致运行时错误。具体的大小限制在任何情况下都取决于实现。


还有另一种异步方式使用blob和filereader。

我没有测试性能。但这是一种不同的思维方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
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"


对于喜欢简短的人,这里还有一个使用Array.reduce的,不会导致堆栈溢出:

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


我的建议是不要使用本地的btoa策略,因为它们不能正确编码所有ArrayBuffer的策略。

重写doms atob()和btoa()。

Since DOMStrings are 16-bit-encoded strings, in most browsers calling window.btoa on a Unicode string will cause a Character Out Of Range exception if a character exceeds the range of a 8-bit ASCII-encoded character.

虽然我从未遇到过这种确切的错误,但我发现我尝试编码的许多ArrayBuffer的编码都不正确。

我要么使用MDN推荐,要么使用GIST。

  • 网址:https://github.com/beatgammit/base64-js
  • https://gist.github.com/jonleighton/958841


我用这个为我工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}


下面是将uint8array转换为base64字符串并再次返回的两个简单函数

1
2
3
4
5
6
7
8
arrayToBase64String(a) {
    return btoa(String.fromCharCode(...a));
}

base64StringToArray(s) {
    let asciiString = atob(s);
    return new Uint8Array([...asciiString].map(char => char.charCodeAt(0)));
}


您可以使用Array.prototype.sliceArrayBuffer派生一个正规数组。使用像Array.prototype.map这样的函数将中的字节转换为字符,而join将它们一起转换为字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
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

}

此方法更快,因为其中没有运行字符串连接。


在我这边,使用chrome navigator,我必须使用dataview()来读取arraybuffer

1
2
3
4
5
6
7
8
9
10
11
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;}

1
2
3
4
5
6
7
8
9
10
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从字符串中解包归档文件,这会更好。