2012-02-13 122 views

回答

142
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

+4

我尝试了链接的非本地实现,它花了1分半钟来转换一个1M大小的缓冲区,而上面的循环代码只花了1秒。 – cshu 2013-06-28 18:12:31

+0

我喜欢这种方法的简单性,但所有的字符串连接都可能是昂贵的。它看起来像构建一个字符数组,并且在最后使用join()方法在Firefox,IE和Safari上速度要快得多(但在Chrome上速度要慢很多):http://jsperf.com/tobase64-实现 – JLRishe 2014-05-14 09:30:37

+0

我正在使用此功能阵列缓冲区base64转换,但我无法取回数组缓冲区。我在这里声明了一个_base64ToArrayBuffer()函数:http://codeshare.io/PT4pb,但是这给了我一个错误,因为:'在'Window'上无法执行'atob':要解码的字符串编码不正确。 – bawejakunal 2015-07-11 13:27:50

46

这对我工作得很好:

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

在ES6,语法是有点简单:

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

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

+26

我更喜欢这种方法的简洁性,但得到“最大调用堆栈大小超出错误”。上面的循环技术可以解决这个问题。 – Jay 2012-09-07 12:26:52

+11

我也遇到堆栈大小错误,所以我使用mobz的答案,它的工作很好。 – 2013-09-03 01:34:07

+0

这工作简洁,谢谢 – duckegg 2014-07-06 16:39:19

-3
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用于解压缩归档从字符串

+0

有什么错? – RouR 2015-07-27 09:07:09

+0

这个函数并没有做它应该做的事情:https://jsfiddle.net/as9t9ebf/ – 2015-12-26 21:55:50

6

我提出这一建议是不要使用本地btoa策略,因为它们不正确编码所有ArrayBuffer的...

rewrite the DOMs atob() and btoa()

由于DOMStrings是16位编码的字符串,在大多数浏览器上一个Unicode字符串调用window.btoa会引起CHARAC如果字符超出8位ASCII编码字符的范围,则超出范围异常。

虽然我从来没有遇到过这种确切的错误,我发现许多我试图编码的ArrayBuffer的已编码不正确。

我会使用MDN建议或要点。

+0

'btoa'不适用于String,但是OP要求'ArrayBuffer'。 – tsh 2017-06-17 03:18:21

+1

非常多,这里有很多片段推荐错误的东西!我多次看到这个错误,人们盲目地使用atob和btoa。 – Kugel 2017-08-24 04:53:23

11

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



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; 
} 
+0

不安全。请参阅@chemoish answer – Kugel 2017-08-24 04:57:32

0

可以通过使用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 

} 

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

+0

不安全。看到@chemoish回答 – Kugel 2017-08-24 04:58:02

17

对于那些谁喜欢总之,这里是一个另一种使用Array.reduce这不会导致堆栈溢出:

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

性感! – Kano 2018-01-04 09:36:43

1

下面是两个简单的功能Uint8Array转换为Base64编码字符串,然后再返回

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

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