我需要一个有效的(读本机)方法来转换一个ArrayBuffer到一个base64字符串,这需要在一个多部分的帖子上使用。


当前回答

这对我来说很有效:

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

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

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

正如评论中指出的,当ArrayBuffer较大时,此方法可能会在某些浏览器中导致运行时错误。确切的大小限制在任何情况下都取决于实现。

其他回答

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从字符串解压缩存档,那么这样做会更好

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

更新的基准测试:https://jsben.ch/wnaZC

这对我来说很有效:

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

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

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

正如评论中指出的,当ArrayBuffer较大时,此方法可能会在某些浏览器中导致运行时错误。确切的大小限制在任何情况下都取决于实现。

还有另一种异步方式使用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"

对于那些喜欢简短的人,这里有另一个使用数组的例子。减少不会导致堆栈溢出:

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