【发布时间】:2012-03-05 06:58:13
【问题描述】:
我需要一种有效的(读取本机)方法将ArrayBuffer 转换为需要在多部分帖子中使用的 base64 字符串。
【问题讨论】:
标签: javascript encoding base64 arraybuffer
我需要一种有效的(读取本机)方法将ArrayBuffer 转换为需要在多部分帖子中使用的 base64 字符串。
【问题讨论】:
标签: javascript encoding base64 arraybuffer
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
【讨论】:
join()ing 他们明显更快(但在 Chrome 上慢得多):jsperf.com/tobase64-implementations
toString('base64') 方法。
Buffer 在浏览器中不存在。
这对我来说很好用:
var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
在 ES6 中,语法稍微简单一些:
const base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
正如 cmets 中所指出的,当ArrayBuffer 很大时,此方法可能会在某些浏览器中导致运行时错误。在任何情况下,确切的大小限制都取决于实现。
【讨论】:
btoa([].reduce.call(new Uint8Array(bufferArray),function(p,c){return p+String.fromCharCode(c)},''))
btoa 对于代码范围 0-255 中的字符是安全的,因为这里就是这种情况(想想Uint8Array 中的 8)。
对于喜欢简短的人来说,这是另一个使用Array.reduce 不会导致堆栈溢出的:
var base64 = btoa(
new Uint8Array(arrayBuffer)
.reduce((data, byte) => data + String.fromCharCode(byte), '')
);
【讨论】:
<amount of Bytes in the buffer> 新字符串。
btoa(new Uint8Array(arraybuffer).reduce((data,byte)=>(data.push(String.fromCharCode(byte)),data),[]).join('')) 怎么样?
btoa(Array.from(new Uint8Array(arraybuffer)).map(b => String.fromCharCode(b)).join('')).
还有另一种异步方式使用 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"
【讨论】:
dataurl.split(',', 2)[1]而不是dataurl.substr(dataurl.indexOf(',')+1)。
readAsDataURL理论上可以返回一个百分比编码的dataURI(看起来jsdom实际上是这种情况)
split 会比substring 更好?
var blob = new Blob([arrayBuffer])
var reader = new FileReader();
reader.onload = function(event){
var base64 = event.target.result
};
reader.readAsDataURL(blob);
【讨论】:
data:*/*;base64,) 才能仅获取 Base64 字符串。见MDN docs
我用过这个并为我工作。
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;
}
【讨论】:
我的建议是不要使用原生 btoa 策略,因为它们不能正确编码所有 ArrayBuffer 的...
rewrite the DOMs atob() and btoa()
由于 DOMStrings 是 16 位编码的字符串,在大多数浏览器中,如果字符超出 8 位 ASCII 编码字符的范围,则对 Unicode 字符串调用 window.btoa 会导致字符超出范围异常。
虽然我从未遇到过这个确切的错误,但我发现我尝试编码的许多 ArrayBuffer 编码不正确。
我会使用 MDN 推荐或要点。
【讨论】:
btoa 不适用于字符串,但 OP 正在询问 ArrayBuffer。
下面是 2 个简单的函数,用于将 Uint8Array 转换为 Base64 字符串并再次返回
arrayToBase64String(a) {
return btoa(String.fromCharCode(...a));
}
base64StringToArray(s) {
let asciiString = atob(s);
return new Uint8Array([...asciiString].map(char => char.charCodeAt(0)));
}
【讨论】:
function 关键字,它应该可以在现代浏览器中使用。
OP 没有指定运行环境,但是如果您使用的是 Node.JS,那么有一种非常简单的方法可以做到这一点。
与官方 Node.JS 文档一致 https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
// This step is only necessary if you don't already have a Buffer Object
const buffer = Buffer.from(yourArrayBuffer);
const base64String = buffer.toString('base64');
此外,例如,如果您在 Angular 下运行,缓冲区类也将在浏览器环境中可用。
【讨论】:
Javascript。所以我更新了我的答案以使其更简洁。我认为这是一个重要的答案,因为我一直在寻找如何做到这一点,但无法找到问题的最佳答案。
如果您可以添加库,base64-arraybuffer:
yarn add base64-arraybuffer
然后:
encode(buffer) - 将 ArrayBuffer 编码为 base64 字符串decode(str) - 将 base64 字符串解码为 ArrayBuffer【讨论】:
您可以使用Array.prototype.slice 从ArrayBuffer 派生一个普通数组。
使用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
}
此方法更快,因为其中没有运行字符串连接。
【讨论】:
在浏览器和Node.js中使用uint8-to-b64包进行编码/解码
【讨论】:
在我身边,使用 Chrome 导航器,我不得不使用 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;}
【讨论】:
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 从字符串中解压存档,这样会更好
【讨论】: