ArrayBuffer 到 base64 编码的字符串

IT技术 javascript encoding base64 arraybuffer
2021-01-10 17:48:37

我需要一种有效的(读取本机)方式将 an 转换ArrayBuffer为需要在多部分帖子中使用的 base64 字符串。

6个回答
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

我从链接中尝试了非本地实现,转换一个 1M 大小的缓冲区需要 1 分半钟,而上面的循环代码只需要 1 秒。
2021-03-13 17:48:37
@JoãoEduardoSoareseSilva 因为不是每个人都在使用 Node - NodeBuffer不存在于浏览器中。
2021-03-23 17:48:37
我想知道为什么每个人都在避免使用本机缓冲区toString('base64')方法。
2021-03-24 17:48:37
我喜欢这种方法的简单性,但所有这些字符串连接都可能代价高昂。看起来join()在 Firefox、IE 和 Safari 上构建一个字符数组并在最后输入它们的速度要快得多(但在 Chrome 上要慢得多):jsperf.com/tobase64-implementations
2021-03-28 17:48:37
我正在尝试使用 angualrjs 和 webapi2 上传 50mb pdf 文件。我正在使用上面的代码,上传文件后,页面崩溃并挂起。在代码行下方,我使用了但在 webapi 方法中获得了空值。"var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));" 请提出任何想法......
2021-04-01 17:48:37

这对我来说很好用:

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

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

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

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

我正在尝试使用 angualrjs 和 webapi2 上传 50mb pdf 文件。我正在使用上面的代码,上传文件后,页面崩溃并挂起。在代码行下方,我使用了但在 webapi 方法中获得了空值。"var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));" 请提出任何想法......
2021-03-11 17:48:37
我也遇到了堆栈大小错误,所以我使用了 mobz 的答案并且效果很好。
2021-03-21 17:48:37
它不适用于大型缓冲区。稍微修改以使其工作:btoa([].reduce.call(new Uint8Array(bufferArray),function(p,c){return p+String.fromCharCode(c)},''))
2021-03-23 17:48:37
@Kugelbtoa对于 0-255 代码范围内的字符是安全的,因为这里就是这种情况(想想 8 in Uint8Array)。
2021-03-29 17:48:37
我更喜欢这种方法的简洁性,但会出现“最大调用堆栈大小超出错误”。上面的循环技术解决了这个问题。
2021-04-05 17:48:37

对于那些喜欢简短的人,这是另一个Array.reduce不会导致堆栈溢出的使用:

var base64 = btoa(
  new Uint8Array(arrayBuffer)
    .reduce((data, byte) => data + String.fromCharCode(byte), '')
);
另一种选择:btoa(Array.from(new Uint8Array(arraybuffer)).map(b => String.fromCharCode(b)).join(''))
2021-03-11 17:48:37
不确定这是否真的很性感。毕竟,您正在创建<amount of Bytes in the buffer>新的字符串。
2021-03-17 17:48:37
无法在“Window”上执行“btoa”:要编码的字符串包含超出 Latin1 范围的字符
2021-03-19 17:48:37
怎么样btoa(new Uint8Array(arraybuffer).reduce((data,byte)=>(data.push(String.fromCharCode(byte)),data),[]).join(''))
2021-03-25 17:48:37

还有另一种异步方式使用 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"
这似乎不能保证工作。根据w3c.github.io/FileAPI/#issue-f80bda5b readAsDataURL理论上可以返回一个百分比编码的 dataURI (在jsdom 中似乎确实如此
2021-03-12 17:48:37
@CarterMedlin 为什么会splitsubstring?
2021-03-29 17:48:37
使用dataurl.split(',', 2)[1]代替dataurl.substr(dataurl.indexOf(',')+1)
2021-03-30 17:48:37
分裂更短。但是 dataurl 可能包含一个或多个逗号(,),split 是不安全的。
2021-04-03 17:48:37
var blob = new Blob([arrayBuffer])

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

reader.readAsDataURL(blob);
我希望我能再次找到这个解决方案,比如 8 小时。我的一天不会被浪费;(谢谢
2021-03-21 17:48:37
我认为您还需要删除 DataURL 标头 ( data:*/*;base64,) 以仅获取 Base64 字符串。查看MDN 文档
2021-03-26 17:48:37
2021-03-31 17:48:37
请在您的答案中添加一些解释。这段代码是什么意思?
2021-04-02 17:48:37
这是迄今为止最快的方法 - 在我有限的测试中比其他方法快几十倍
2021-04-04 17:48:37