我有一个webSocket通信,我收到base64编码的字符串,将其转换为uint8并继续工作,但现在我需要发送回来,我得到了uint8数组,并且需要将其转换为base64字符串,所以我可以发送。 我怎样才能进行这种转换呢?
答案 0 :(得分:139)
如果您的数据可能包含多字节序列(不是纯ASCII序列)且浏览器有TextDecoder,那么您应该使用它来解码数据(指定TextDecoder所需的编码):
var u8 = new Uint8Array([65, 66, 67, 68]);
var decoder = new TextDecoder('utf8');
var b64encoded = btoa(decoder.decode(u8));
如果您需要支持browsers that do not have 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); }));
如果您有非常大的数组缓冲区,则apply可能会失败,您可能需要对缓冲区进行分块(基于@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));
答案 1 :(得分:16)
function Uint8ToBase64(u8Arr){
var CHUNK_SIZE = 0x8000; //arbitrary number
var index = 0;
var length = u8Arr.length;
var result = '';
var slice;
while (index < length) {
slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length));
result += String.fromCharCode.apply(null, slice);
index += CHUNK_SIZE;
}
return btoa(result);
}
如果你有一个非常大的Uint8Array,你可以使用这个功能。这是针对Javascript的,在FileReader readAsArrayBuffer的情况下可能很有用。
答案 2 :(得分:15)
非常简单的JavaScript解决方案和测试!
ToBase64 = function (u8) {
return btoa(String.fromCharCode.apply(null, u8));
}
FromBase64 = function (str) {
return atob(str).split('').map(function (c) { return c.charCodeAt(0); });
}
var u8 = new Uint8Array(256);
for (var i = 0; i < 256; i++)
u8[i] = i;
var b64 = ToBase64(u8);
console.debug(b64);
console.debug(FromBase64(b64));
答案 3 :(得分:2)
我将添加另一个适用于不可打印范围的解决方案。我的猜测是,这比链接TextEncoder
和btoa
更快。
var blob = new Blob( [ uint8ArrayBuffer ], { type: "image/jpeg" } );
var imageUrl = URL.createObjectURL( blob );
这是使用HTML5 API,因此当然不能在Node或其他基于JS的服务器上运行。您可以看到演示here。
答案 4 :(得分:2)
使用本机浏览器功能对带有任意数据(不一定是 UTF-8)的 UInt8Array
进行 base64 编码:
const base64_arraybuffer = async (data) => {
// Use a FileReader to generate a base64 data URI
const base64url = await new Promise((r) => {
const reader = new FileReader()
reader.onload = () => r(reader.result)
reader.readAsDataURL(new Blob([data]))
})
/*
The result looks like
"data:application/octet-stream;base64,<your base64 data>",
so we split off the beginning:
*/
return base64url.split(",", 2)[1]
}
// example use:
await base64_arraybuffer(new UInt8Array([1,2,3,100,200]))
答案 5 :(得分:1)
(将Base64字符串解码为Uint8Array或支持Unicode的ArrayBuffer)
答案 6 :(得分:1)
这是一个JS函数:
该功能是必需的,因为Chrome不接受base64编码的字符串 作为pushManager.subscribe中applicationServerKey的值 https://bugs.chromium.org/p/chromium/issues/detail?id=802280
function urlBase64ToUint8Array(base64String) {
var padding = '='.repeat((4 - base64String.length % 4) % 4);
var base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
var rawData = window.atob(base64);
var outputArray = new Uint8Array(rawData.length);
for (var i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
答案 7 :(得分:1)
已经提出的所有解决方案都存在严重问题。一些解决方案无法在大型数组上运行,某些解决方案提供错误的输出,某些解决方案在中间字符串包含多字节字符的情况下在btoa调用上引发错误,有些解决方案消耗的内存超过了所需。
因此,我实现了直接转换功能,该功能无论输入如何都可以正常工作。它每秒可在我的计算机上转换约500万个字节。
https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727
答案 8 :(得分:0)
如果您使用的是Node.js,则可以使用此代码将Uint8Array转换为base64
var b64 = Buffer.from(u8).toString('base64');
答案 9 :(得分:0)
Mozilla Developer Network website显示了一种非常好的解决方法:
function btoaUTF16 (sString) {
var aUTF16CodeUnits = new Uint16Array(sString.length);
Array.prototype.forEach.call(aUTF16CodeUnits, function (el, idx, arr) { arr[idx] = sString.charCodeAt(idx); });
return btoa(String.fromCharCode.apply(null, new Uint8Array(aUTF16CodeUnits.buffer)));
}
function atobUTF16 (sBase64) {
var sBinaryString = atob(sBase64), aBinaryView = new Uint8Array(sBinaryString.length);
Array.prototype.forEach.call(aBinaryView, function (el, idx, arr) { arr[idx] = sBinaryString.charCodeAt(idx); });
return String.fromCharCode.apply(null, new Uint16Array(aBinaryView.buffer));
}
var myString = "☸☹☺☻☼☾☿";
var sUTF16Base64 = btoaUTF16(myString);
console.log(sUTF16Base64); // Shows "OCY5JjomOyY8Jj4mPyY="
var sDecodedString = atobUTF16(sUTF16Base64);
console.log(sDecodedString); // Shows "☸☹☺☻☼☾☿"
答案 10 :(得分:0)
在以下解决方案中,我省略了对字符串的转换。 IDEA正在关注:
=
或==
添加为结果以下解决方案适用于3字节的块,因此适用于大型阵列。将base64转换为二进制数组(无atob
)的类似解决方案是HERE
function bytesArrToBase64(arr) {
const abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // base64 alphabet
const bin = n => n.toString(2).padStart(8,0); // convert num to 8-bit binary string
const l = arr.length
let result = '';
for(let i=0; i<=(l-1)/3; i++) {
let c1 = i*3+1>=l; // case when "=" is on end
let c2 = i*3+2>=l; // case when "=" is on end
let chunk = bin(arr[3*i]) + bin(c1? 0:arr[3*i+1]) + bin(c2? 0:arr[3*i+2]);
let r = chunk.match(/.{1,6}/g).map((x,j)=> j==3&&c2 ? '=' :(j==2&&c1 ? '=':abc[+('0b'+x)]));
result += r.join('');
}
return result;
}
// ----------
// TEST
// ----------
let test = "Alice's Adventure in Wondeland.";
let testBytes = [...test].map(c=> c.charCodeAt(0) );
console.log('test string:', test);
console.log('bytes:', JSON.stringify(testBytes));
console.log('btoa ', btoa(test));
console.log('bytesArrToBase64', bytesArrToBase64(testBytes));
答案 11 :(得分:0)
使用以下命令将uint8数组转换为base64编码的字符串
function arrayBufferToBase64(buffer) {
var binary = '';
var bytes = [].slice.call(new Uint8Array(buffer));
bytes.forEach((b) => binary += String.fromCharCode(b));
return window.btoa(binary);
};
答案 12 :(得分:-3)
如果你想要的只是一个base64编码器的JS实现,以便你可以发回数据,你可以尝试btoa
函数。
b64enc = btoa(uint);
关于btoa的一些快速说明 - 它是非标准的,因此浏览器不会被迫支持它。
但是,大多数浏览器都有。至少是大的。 atob
是相反的转换。
如果您需要不同的实现,或者您发现浏览器不知道您在谈论什么的边缘情况,那么搜索JS的base64编码器并不会太难。
我认为由于某种原因,我公司的网站上有3个人在附近......
答案 13 :(得分:-3)
npm install google-closure-library --save
require("google-closure-library");
goog.require('goog.crypt.base64');
var result =goog.crypt.base64.encodeByteArray(Uint8Array.of(1,83,27,99,102,66));
console.log(result);
$node index.js
会将 AVMbY2Y = 写入控制台。