574

How to convert uint8 Array to base64 Encoded String?

 3 years ago
source link: https://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
How to convert uint8 Array to base64 Encoded String?

Join Stack Overflow to learn, share knowledge, and build your career.

Asked 8 years, 6 months ago
Active 1 month ago
Viewed 113k times

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?

asked Oct 3 '12 at 13:52

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.

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.

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

answered Jul 19 '19 at 11:09

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):

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.

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

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:

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:

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));
answered Oct 3 '12 at 17:03

Very simple solution and test for 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));
answered Mar 16 '16 at 20:54

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

var b64 = Buffer.from(u8).toString('base64');
answered Mar 23 '19 at 7:30
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.

To base64-encode a UInt8Array with arbitrary data (not necessarily UTF-8) using native browser functionality:

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]))
answered Feb 4 at 13:00

Use the following to convert uint8 array to base64 encoded string

function arrayBufferToBase64(buffer) {
            var binary = '';
            var bytes = [].slice.call(new Uint8Array(buffer));
            bytes.forEach((b) => binary += String.fromCharCode(b));
            return window.btoa(binary);
        };
answered Nov 5 '20 at 4:17

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;
}
answered Sep 24 '18 at 16:30

Pure JS - no string middlestep (no btoa)

In below solution I omit conversion to string. IDEA is following:

  • join 3 bytes (3 array elements) and you get 24-bits
  • split 24bits to four 6-bit numbers (which take values from 0 to 63)
  • use that numbers as index in base64 alphabet
  • corner case: when input byte array the length is not divided by 3 then add = or == to result

Solution below works on 3-bytes chunks so it is good for large arrays. Similar solution to convert base64 to binary array (without atob) is HERE

answered Jun 13 '20 at 16:35

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...

answered Oct 3 '12 at 13:58

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.

answered Jul 27 '18 at 3:48

Your Answer

Sign up or log in

Sign up using Google
Sign up using Facebook
Sign up using Email and Password

Post as a guest

Name
Email

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged javascript arrays base64 or ask your own question.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK