programing tip

uint8 배열을 base64 인코딩 문자열로 변환하는 방법은 무엇입니까?

itbloger 2020. 11. 10. 07:53
반응형

uint8 배열을 base64 인코딩 문자열로 변환하는 방법은 무엇입니까?


webSocket 통신이 있고 base64로 인코딩 된 문자열을 받아서 uint8로 변환하여 작업하지만 이제 다시 보내야하고 uint8 배열을 가져 와서 base64 문자열로 변환해야하므로 보낼 수 있습니다. 이 변환을 어떻게 할 수 있습니까?


이미 제안 된 모든 솔루션에는 심각한 문제가 있습니다. 일부 솔루션은 대형 배열에서 작동하지 않고 일부는 잘못된 출력을 제공하며 일부는 중간 문자열에 멀티 바이트 문자가 포함 된 경우 btoa 호출에 오류가 발생하고 일부는 필요한 것보다 더 많은 메모리를 소비합니다.

그래서 입력에 관계없이 작동하는 직접 변환 기능을 구현했습니다. 내 컴퓨터에서 초당 약 5 백만 바이트를 변환합니다.

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


데이터에 다중 바이트 시퀀스 (일반 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 (멀티 바이트 유니 코드 / 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));

매우 간단한 솔루션과 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));

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의 경우 유용 할 수 있습니다.


EDIT 2019 : 나는 이것을 검토했고 이것은 이미지보내는 해결책이 아니며 로컬로만 표시합니다. createObjectURLbase64 데이터를 생성하지 않지만 DOMString, 이는 단순히 사용할 수있는 짧은 브라우저 별 URL img.src입니다.


I'll add another solution that works with non-printable ranges. This is way faster than chaining TextEncoder and btoa when all you need is to display an image received as a byte array.

var blob = new Blob( [ uint8ArrayBuffer ], { type: "image/jpeg" } );
var imageUrl = URL.createObjectURL( blob );

This is using HTML5 APIs, and so will not work on Node or other JS based servers, of course. You can see a demo here.


See here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding#Appendix.3A_Decode_a_Base64_string_to_Uint8Array_or_ArrayBuffer

(Decode a Base64 string to Uint8Array or ArrayBuffer with Unicode support)


Here is a JS Function to this:

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

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

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

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

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

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. atob is the opposite conversion.

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.

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


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

참고URL : https://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string

반응형