ArrayBuffer to base64 encoded string

JavascriptEncodingBase64Arraybuffer

Javascript Problem Overview


I need an efficient (read native) way to convert an ArrayBuffer to a base64 string which needs to be used on a multipart post.

Javascript Solutions


Solution 1 - Javascript

function _arrayBufferToBase64( buffer ) {
	var binary = '';
	var bytes = new Uint8Array( buffer );
	var len = bytes.byteLength;
	for (var i = 0; i < len; i++) {
		binary += String.fromCharCode( bytes[ i ] );
	}
	return window.btoa( binary );
}

but, non-native implementations are faster e.g. https://gist.github.com/958841 see http://jsperf.com/encoding-xhr-image-data/6

Updated benchmarks: https://jsben.ch/wnaZC

Solution 2 - Javascript

This works fine for me:

var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));

In ES6, the syntax is a little simpler:

const base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));

As pointed out in the comments, this method may result in a runtime error in some browsers when the ArrayBuffer is large. The exact size limit is implementation dependent in any case.

Solution 3 - Javascript

For those who like it short, here's an other one using Array.reduce which will not cause stack overflow:

var base64 = btoa(
  new Uint8Array(arrayBuffer)
    .reduce((data, byte) => data + String.fromCharCode(byte), '')
);

Solution 4 - Javascript

There is another asynchronous way use Blob and FileReader.

I didn't test the performance. But it is a different way of thinking.

function arrayBufferToBase64( buffer, callback ) {
    var blob = new Blob([buffer],{type:'application/octet-binary'});
    var reader = new FileReader();
    reader.onload = function(evt){
        var dataurl = evt.target.result;
        callback(dataurl.substr(dataurl.indexOf(',')+1));
    };
    reader.readAsDataURL(blob);
}

//example:
var buf = new Uint8Array([11,22,33]);
arrayBufferToBase64(buf, console.log.bind(console)); //"CxYh"

Solution 5 - Javascript

var blob = new Blob([arrayBuffer])
    
var reader = new FileReader();
reader.onload = function(event){
   var base64 =   event.target.result
};
   
reader.readAsDataURL(blob);

Solution 6 - Javascript

I used this and works for me.

function arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}



function base64ToArrayBuffer(base64) {
    var binary_string =  window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array( len );
    for (var i = 0; i < len; i++)        {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}

Solution 7 - Javascript

My recommendation for this is to NOT use native btoa strategies—as they don't correctly encode all ArrayBuffer's…

rewrite the DOMs atob() and btoa()

> Since DOMStrings are 16-bit-encoded strings, in most browsers calling window.btoa on a Unicode string will cause a Character Out Of Range exception if a character exceeds the range of a 8-bit ASCII-encoded character.

While I have never encountered this exact error, I have found that many of the ArrayBuffer's I have tried to encode have encoded incorrectly.

I would either use MDN recommendation or gist.

Solution 8 - Javascript

Below are 2 simple functions for converting Uint8Array to Base64 String and back again

arrayToBase64String(a) {
    return btoa(String.fromCharCode(...a));
}

base64StringToArray(s) {
    let asciiString = atob(s);
    return new Uint8Array([...asciiString].map(char => char.charCodeAt(0)));
}

Solution 9 - Javascript

The OP did not specify the Running Enviroment but if you are using Node.JS there is a very simple way to do such thing.

Accordig with the official Node.JS docs https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings

// This step is only necessary if you don't already have a Buffer Object
const buffer = Buffer.from(yourArrayBuffer);

const base64String = buffer.toString('base64');

Also, If you are running under Angular for example, the Buffer Class will also be made available in a Browser Environment.

Solution 10 - Javascript

If you're okay with adding a library, base64-arraybuffer:

yarn add base64-arraybuffer

then:

  • encode(buffer) - Encodes ArrayBuffer into base64 string
  • decode(str) - Decodes base64 string to ArrayBuffer

Solution 11 - Javascript

You can derive a normal array from the ArrayBuffer by using Array.prototype.slice. Use a function like Array.prototype.map to convert bytes in to characters and join them together to forma string.

function arrayBufferToBase64(ab){

    var dView = new Uint8Array(ab);   //Get a byte view        
    
    var arr = Array.prototype.slice.call(dView); //Create a normal array        

    var arr1 = arr.map(function(item){        
      return String.fromCharCode(item);    //Convert
    });
    
    return window.btoa(arr1.join(''));   //Form a string

}

This method is faster since there are no string concatenations running in it.

Solution 12 - Javascript

ABtoB64(ab) {
	return new Promise(res => {
		const fr = new FileReader();
		fr.onload = ({target: {result: s}}) => res(s.slice(s.indexOf(';base64,') + 8));
		fr.readAsDataURL(new Blob([ab]));
	});
}

asynchronous method using file reader.

Solution 13 - Javascript

Use uint8-to-b64 package to do encoding/decoding in browser and Node.js

Solution 14 - Javascript

By my side, using Chrome navigator, I had to use DataView() to read an arrayBuffer

function _arrayBufferToBase64( tabU8A ) {
var binary = '';
let lecteur_de_donnees = new DataView(tabU8A);
var len = lecteur_de_donnees.byteLength;
var chaine = '';
var pos1;
for (var i = 0; i < len; i++) {
    binary += String.fromCharCode( lecteur_de_donnees.getUint8( i ) );
}
chaine = window.btoa( binary )
return chaine;}

Solution 15 - Javascript

function _arrayBufferToBase64(uarr) {
    var strings = [], chunksize = 0xffff;
    var len = uarr.length;

    for (var i = 0; i * chunksize < len; i++){
        strings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize)));
    }

    return strings.join("");
}

This is better, if you use JSZip for unpack archive from string

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionzaheerView Question on Stackoverflow
Solution 1 - JavascriptmobzView Answer on Stackoverflow
Solution 2 - JavascriptGOTO 0View Answer on Stackoverflow
Solution 3 - JavascriptgkunzView Answer on Stackoverflow
Solution 4 - JavascriptcuixipingView Answer on Stackoverflow
Solution 5 - JavascriptAlexView Answer on Stackoverflow
Solution 6 - JavascriptElias VargasView Answer on Stackoverflow
Solution 7 - JavascriptchemoishView Answer on Stackoverflow
Solution 8 - JavascriptSteve DixonView Answer on Stackoverflow
Solution 9 - JavascriptJoão EduardoView Answer on Stackoverflow
Solution 10 - JavascriptHendy IrawanView Answer on Stackoverflow
Solution 11 - JavascriptCharlieView Answer on Stackoverflow
Solution 12 - JavascriptAliView Answer on Stackoverflow
Solution 13 - Javascriptuser14612834View Answer on Stackoverflow
Solution 14 - JavascriptLouvet JeanView Answer on Stackoverflow
Solution 15 - JavascriptRouRView Answer on Stackoverflow