Javascript 如何将 uint8 数组转换为 base64 编码字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12710001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 11:04:45  来源:igfitidea点击:

How to convert uint8 Array to base64 Encoded String?

javascriptbase64

提问by Caio Keto

I got a webSocket comunication, I recieve base64 encoded string, convert it to uint8 and work on it, but now I need to send back, I got the uint8 array, and need to convert it to base64 string, so I can send it. How can I make this convertion?

我有一个 webSocket 通信,我收到 base64 编码的字符串,将其转换为 uint8 并对其进行处理,但现在我需要发回,我得到了 uint8 数组,并且需要将其转换为 base64 字符串,以便我可以发送它。我怎样才能进行这种转换?

采纳答案by Egor Nepomnyaschih

All solutions already proposed have severe problems. Some solutions fail to work on large arrays, some provide wrong output, some throw an error on btoa call if an intermediate string contains multibyte characters, some consume more memory than needed.

已经提出的所有解决方案都有严重的问题。一些解决方案无法在大型数组上工作,一些提供错误的输出,如果中间字符串包含多字节字符,一些会在 btoa 调用时抛出错误,一些会消耗比需要更多的内存。

So I implemented a direct conversion function which just works regardless of the input. It converts about 5 million bytes per second on my machine.

所以我实现了一个直接转换功能,无论输入如何,它都可以工作。它在我的机器上每秒转换大约 500 万字节。

https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727

https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727

回答by kanaka

If your data may contain multi-byte sequences (not a plain ASCII sequence) and your browser has TextDecoder, then you should use that to decode your data (specify the required encoding for the TextDecoder):

如果您的数据可能包含多字节序列(不是纯 ASCII 序列)并且您的浏览器具有TextDecoder,那么您应该使用它来解码您的数据(为 TextDecoder 指定所需的编码):

var u8 = new Uint8Array([65, 66, 67, 68]);
var decoder = new TextDecoder('utf8');
var b64encoded = btoa(decoder.decode(u8));

If you need to support browsers that do not have TextDecoder(currently just IE and Edge), then the best option is to use a TextDecoder polyfill.

如果你需要支持没有 TextDecoder 的浏览器(目前只有 IE 和 Edge),那么最好的选择是使用TextDecoder polyfill

If your data contains plain ASCII (not multibyte Unicode/UTF-8) then there is a simple alternative using String.fromCharCodethat should be fairly universally supported:

如果您的数据包含纯 ASCII(不是多字节 Unicode/UTF-8),那么有一个简单的替代方法String.fromCharCode应该得到普遍支持:

var ascii = new Uint8Array([65, 66, 67, 68]);
var b64encoded = btoa(String.fromCharCode.apply(null, ascii));

And to decode the base64 string back to a Uint8Array:

并将 base64 字符串解码回 Uint8Array:

var u8_2 = new Uint8Array(atob(b64encoded).split("").map(function(c) {
    return c.charCodeAt(0); }));

If you have very large array buffers then the apply may fail and you may need to chunk the buffer (based on the one posted by @RohitSengar). Again, note that this is only correct if your buffer only contains non-multibyte ASCII characters:

如果您有非常大的数组缓冲区,那么应用可能会失败,您可能需要对缓冲区进行分块(基于@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));

回答by impactro

Very simple solution and test for JavaScript!

非常简单的 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));

回答by Rohit Singh Sengar

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);
}

You can use this function if you have a very large Uint8Array. This is for Javascript, can be useful in case of FileReader readAsArrayBuffer.

如果你有一个非常大的 Uint8Array,你可以使用这个函数。这是针对 Javascript 的,在 FileReader readAsArrayBuffer 的情况下很有用。

回答by Fiach Reid

If you are using Node.js then you can use this code to convert Uint8Array to base64

如果您使用的是 Node.js,那么您可以使用此代码将 Uint8Array 转换为 base64

var b64 = Buffer.from(u8).toString('base64');

回答by lucss

Here is a JS Function to this:

这是一个 JS 函数:

This function is needed because Chrome doesn't accept a base64 encoded string as value for applicationServerKey in pushManager.subscribe yet https://bugs.chromium.org/p/chromium/issues/detail?id=802280

需要此功能是因为 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;
}

回答by Rosberg Linhares

A very good approach to this is shown at the Mozilla Developer Network website:

Mozilla 开发人员网络网站上显示了一个非常好的方法:

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 "???????"

回答by Norguard

If all you want is a JS implementation of a base64-encoder, so that you can send data back, you can try the btoafunction.

如果您只想要一个 base64 编码器的 JS 实现,以便您可以将数据发送回来,那么您可以尝试该btoa功能。

b64enc = btoa(uint);

A couple of quick notes on btoa - it's non-standard, so browsers aren't forced to support it. However, most browsers do. The big ones, at least. atobis the opposite conversion.

关于 btoa 的几个快速说明 - 它是非标准的,因此浏览器不会被迫支持它。但是,大多数浏览器都可以。大的,至少。atob是相反的转换。

If you need a different implementation, or you find an edge-case where the browser has no idea what you're talking about, searching for a base64 encoder for JS wouldn't be too hard.

如果您需要不同的实现,或者您发现浏览器不知道您在说什么的边缘情况,那么为 JS 搜索 base64 编码器不会太难。

I think there are 3 of them hanging around on my company's website, for some reason...

我认为其中有 3 个在我公司的网站上闲逛,出于某种原因......

回答by mancini0

npm install google-closure-library --save

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.jswould write AVMbY2Y=to the console.

$node index.js会将AVMbY2Y=写入控制台。