我有一个 webSocket 通信,我收到 base64 编码的字符串,将其转换为 uint8 并对其进行处理,但现在我需要发回,我得到了 uint8 数组,需要将其转换为 base64 字符串,以便我可以发送它。我怎样才能进行这种转换?
原文由 Caio Keto 发布,翻译遵循 CC BY-SA 4.0 许可协议
我有一个 webSocket 通信,我收到 base64 编码的字符串,将其转换为 uint8 并对其进行处理,但现在我需要发回,我得到了 uint8 数组,需要将其转换为 base64 字符串,以便我可以发送它。我怎样才能进行这种转换?
原文由 Caio Keto 发布,翻译遵循 CC BY-SA 4.0 许可协议
如果您的数据可能包含多字节序列(不是普通的 ASCII 序列)并且您的浏览器有 TextDecoder ,那么您应该使用它来解码您的数据(为 TextDecoder 指定所需的编码):
var u8 = new Uint8Array([65, 66, 67, 68]);
var decoder = new TextDecoder('utf8');
var b64encoded = btoa(decoder.decode(u8));
如果您需要支持 没有 TextDecoder 的浏览器(目前只有 IE 和 Edge),那么最好的选择是使用 TextDecoder polyfill 。
如果您的数据包含纯 ASCII(不是多字节 Unicode/UTF-8),那么有一个简单的替代方案,使用 String.fromCharCode
应该得到相当普遍的支持:
var ascii = new Uint8Array([65, 66, 67, 68]);
var b64encoded = btoa(String.fromCharCode.apply(null, ascii));
并将 base64 字符串解码回 Uint8Array:
var u8_2 = new Uint8Array(atob(b64encoded).split("").map(function(c) {
return c.charCodeAt(0); }));
如果您有非常大的数组缓冲区,那么应用可能会失败,您可能需要对缓冲区进行分块(基于@RohitSengar 发布的)。再次注意,只有当您的缓冲区仅包含非多字节 ASCII 字符时,这才是正确的:
function Uint8ToString(u8a){
var CHUNK_SZ = 0x8000;
var c = [];
for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
}
return c.join("");
}
// Usage
var u8 = new Uint8Array([65, 66, 67, 68]);
var b64encoded = btoa(Uint8ToString(u8));
原文由 kanaka 发布,翻译遵循 CC BY-SA 4.0 许可协议
13 回答12.7k 阅读
7 回答1.9k 阅读
3 回答1.1k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
6 回答809 阅读✓ 已解决
6 回答1k 阅读
2 回答1.3k 阅读✓ 已解决
已经提出的所有解决方案都存在严重问题。有些解决方案无法在大型数组上运行,有些提供错误的输出,如果中间字符串包含多字节字符,有些会在 btoa 调用时抛出错误,有些会消耗比需要更多的内存。
所以我实现了一个直接转换功能,无论输入如何,它都能正常工作。它在我的机器上每秒转换大约 500 万字节。
https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727