Javascript ArrayBuffer到base64编码字符串

Javascript ArrayBuffer到base64编码字符串,javascript,encoding,base64,arraybuffer,Javascript,Encoding,Base64,Arraybuffer,我需要一种高效的(读取本机)方法将ArrayBuffer转换为需要在多部分post上使用的base64字符串 函数_arrayBufferToBase64(缓冲区){ function _arrayBufferToBase64( buffer ) { var binary = ''; var bytes = new Uint8Array( buffer ); var len = bytes.byteLength; for (var i = 0; i < le

我需要一种高效的(读取本机)方法将
ArrayBuffer
转换为需要在多部分post上使用的base64字符串

函数_arrayBufferToBase64(缓冲区){
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 );
}
var二进制=“”; var字节=新的Uint8Array(缓冲区); var len=字节数。字节长度; 对于(变量i=0;i
但是,非本机实现速度更快,例如。
请参见

这对我来说很好:

var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
在ES6中,语法稍微简单一些:

const base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
正如注释中指出的,当
ArrayBuffer
较大时,此方法可能会在某些浏览器中导致运行时错误。确切的大小限制在任何情况下都取决于实现。

函数\u arrayBufferToBase64(uarr){
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("");
}
var strings=[],chunksize=0xffff; var len=uarr.长度; 对于(var i=0;i*chunksize

如果您使用JSZip从字符串解包归档,这会更好,我的建议是不要使用本机
btoa
策略,因为它们不能正确编码所有
ArrayBuffer

由于DOMStrings是16位编码的字符串,在大多数浏览器中,如果字符超出8位ASCII编码字符的范围,则对Unicode字符串调用window.btoa将导致字符超出范围异常

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

我会使用MDN推荐或gist


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

我用这个,为我工作

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;
}
函数arrayBufferToBase64(缓冲区){
var二进制=“”;
var字节=新的Uint8Array(缓冲区);
var len=字节数。字节长度;
对于(变量i=0;i
您可以使用
array.prototype.slice
ArrayBuffer
派生一个普通数组。 使用类似于
Array.prototype.map
的函数将字节转换为字符,并
将它们连接在一起形成字符串

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

}

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

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

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

下面是两个简单的函数,用于将Uint8Array转换为Base64字符串,然后再转换回来

arrayToBase64String(a) {
    return btoa(String.fromCharCode(...a));
}

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

在我这边,使用Chrome navigator,我必须使用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;}
函数_arrayBufferToBase64(tabU8A){
var二进制=“”;
让lecteur_de_donnees=新数据视图(tabU8A);
var len=Lecker_de_donnees.bytellength;
var chaine='';
var-pos1;
对于(变量i=0;i
OP没有指定运行环境,但如果您使用的是Node.JS,则有一种非常简单的方法来完成此操作

与官方Node.JS文档一致


此外,例如,如果您在Angular下运行,缓冲区类也将在浏览器环境中可用。

如果您可以添加库,请使用package在Browser和Node.js中进行编码/解码:

纱线添加base64阵列缓冲器
然后:

  • 编码(缓冲区)
    -将ArrayBuffer编码为base64字符串
  • 解码(str)
    -将base64字符串解码为ArrayBuffer

为了简洁起见,我更喜欢这种方法,但会得到“超出最大调用堆栈大小的错误”。上面的循环技术解决了这个问题。我也遇到了堆栈大小错误,所以我使用了mobz的答案,效果很好。它不适用于大型缓冲区。为使其正常工作而进行的轻微修改:
btoa([].reduce.call(新的Uint8Array(bufferArray),函数(p,c){return p+String.fromCharCode(c)}'))
我正在尝试使用angualrjs和webapi2上传50mb的pdf文件。我使用的是上面的代码,上传文件后,页面崩溃并被挂起。在代码行下面,我被使用了,但在webapi方法中得到了空值。“var base64String=btoa(String.fromCharCode.apply(null,新的Uint8Array(arrayBuffer));”请提出任何想法…@Kugel
btoa
对于代码范围为0-255的字符是安全的,因为这里就是这种情况(考虑一下
Uint8Array
中的8)。我从链接尝试了非本机实现,转换一个1米大小的缓冲区需要1分钟半的时间,而上面的循环代码只需要1秒。我喜欢这种方法的简单性,但所有的字符串串联都可能代价高昂。看起来在Firefox、IE和Safari上构建一个字符数组并
join()。我使用的是上面的代码,上传文件后,页面崩溃并被挂起。在代码行下面,我被使用了,但在webapi方法中得到了空值。“var base64String=btoa(String.fromCharCode.apply(null,新Uint8Array(arrayBuffer));”请提出任何想法……我想知道为什么每个人都在避免使用本机缓冲区
到字符串('base64')
方法。@Joãoeduardoaresisilva,因为不是每个人都在使用节点的
缓冲区
var blob = new Blob([arrayBuffer])

var reader = new FileReader();
reader.onload = function(event){
   var base64 =   event.target.result
};

reader.readAsDataURL(blob);
// This step is only necessary if you don't already have a Buffer Object
const buffer = Buffer.from(yourArrayBuffer);

const base64String = buffer.toString('base64');