ArrayBuffer to base64 encoded string
Solution 1
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
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
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
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
var blob = new Blob([arrayBuffer])
var reader = new FileReader();
reader.onload = function(event){
var base64 = event.target.result
};
reader.readAsDataURL(blob);
Related videos on Youtube
zaheer
Updated on May 07, 2022Comments
-
zaheer about 2 years
I need an efficient (read native) way to convert an
ArrayBuffer
to a base64 string which needs to be used on a multipart post. -
Jason over 11 yearsI like this method better for conciseness, but get a "maximum call stack size exceeded error". The loop technique above gets around that.
-
cshu almost 11 yearsI tried the non-native implementation from the link and it took 1min and half to convert a 1M size buffer while the loop code above only took 1sec.
-
David Jones over 10 yearsI'm also getting a stack size error, so I used mobz's answer and it worked great.
-
JLRishe about 10 yearsI like the simplicity of this approach, but all that string concatenation can be costly. It looks like building an array of the characters and
join()
ing them at the end is significantly faster on Firefox, IE, and Safari (but quite a lot slower on Chrome): jsperf.com/tobase64-implementations -
bawejakunal almost 9 yearsI am using this function for array buffer to base64 conversion but I am not able to get back the array buffer. I have wrriten a _base64ToArrayBuffer() function here: codeshare.io/PT4pb but that gives me an error as:
Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
-
RouR almost 9 yearsthis is not worked this JSZip. i find another way github.com/michael/github/issues/137
-
laggingreflex over 8 yearsIt didn't work for large buffers. Slight modification to make it work:
btoa([].reduce.call(new Uint8Array(bufferArray),function(p,c){return p+String.fromCharCode(c)},''))
-
prabhakaran S over 7 yearsI am trying 50mb pdf file upload using angualrjs and webapi2. I am using above line code , after upload file, the page got crashed and hanged . Below line of code ,I was used but getting null value in webapi method. "var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));" please suggest any idea ...
-
prabhakaran S over 7 yearsI am trying 50mb pdf file upload using angualrjs and webapi2. I am using above line code , after upload file, the page got crashed and hanged . Below line of code ,I was used but getting null value in webapi method. "var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));" please suggest any idea ...
-
hg. over 7 yearsThis is not binary safe. Does anyone know about a binary safe option?
-
BelgoCanadian about 7 yearscould you add the ultimate markup/image string to your answer as well by any chance? I have BMP images stored in SQL that I'm trying to display but this code isn't working: 'data:image/bmp;base64,' + btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
-
GOTO 0 about 7 years@BelgoCanadian I don't see what's wrong with that expression. See here for your question. If this doesn't help then you should ask a new question and provide some more information.
-
tsh almost 7 years
btoa
not works on String, but OP is askingArrayBuffer
. -
Kugel over 6 yearsVery much this, so many snippets here that recommend the wrong thing! I've seen this error multiple times, where people blindly use atob and btoa.
-
Kugel over 6 yearsNot safe. See @chemoish answer
-
Kugel over 6 yearsNot safe. See @chemoish answer
-
Kugel over 6 yearsNot safe. See @chemoish answer
-
Kugel over 6 yearsNot safe. See @chemoish answer
-
GOTO 0 over 6 years@Kugel
btoa
is safe for characters in the code range 0-255, as this is here the case (Think about the 8 inUint8Array
). -
Joe over 6 yearsUnfortunately won't work in node.js. Because of node.js' Utf-8 string encoding
String.fromCharCode()
behave different for byte values >= 0x80. -
Neonit about 6 yearsNot sure if that's really sexy. After all, you're creating
<amount of Bytes in the buffer>
new strings. -
Roy Tinker over 5 yearsHow about
btoa(new Uint8Array(arraybuffer).reduce((data,byte)=>(data.push(String.fromCharCode(byte)),data),[]).join(''))
? -
user1153660 over 5 yearsThis is a confusing answer. That does not look look like valid JavaScript and is a Uint8Array an ArrayBuffer?
-
Carter Medlin over 5 yearsUse
dataurl.split(',', 2)[1]
instead ofdataurl.substr(dataurl.indexOf(',')+1)
. -
Yeti over 5 years@user1153660 Add the
function
keyword and it should work in a modern browser. -
Jamesernator about 5 yearsAll array buffers should be encoded fine using the strategies in other answers, atob/btoa is only a problem for text that contains characters greater than 0xFF (which byte arrays by definition do not). The MDN warning doesn't apply because when using the strategy in the other answers you are guaranteed to have a string that only consists of ASCII characters as any value from a Uint8Array is guaranteed to be between 0 and 255 which means String.fromCharCode is guaranteed to return a character that is not out of range.
-
Nicolo almost 5 yearsAwesome! btoa(String.fromCharCode(...a)); is shortest version I have seen so far to encode Uint8Array.
-
T S over 4 yearsThis doesn't seem to be guaranteed to work. According to w3c.github.io/FileAPI/#issue-f80bda5b
readAsDataURL
could theoretically return a percent encoded dataURI (And it seems it is actually the case in jsdom) -
T S over 4 years@CarterMedlin Why would
split
be better thansubstring
? -
cuixiping over 4 yearssplit is shorter. but dataurl may contains one or more commas(,), split is not safe.
-
Oscar over 4 yearsAdd some explanation to your answer please. What does this code mean?
-
Pawel Psztyc over 4 yearsThis looks good but if the array is too huge it will throw maximum call stack size exceeded error.
-
spenceryue over 4 yearsSimilar helpful MDN example.
-
jitin over 4 yearsthis is by far the fastest approach - tens of times faster than the other ones in my limited testing
-
Kaiser Shahid over 4 yearsi wish i'd found this solution like 8 hours again. my day would not have been wasted ;( thank you
-
David Callanan about 4 years@bawejakunal Seems to work find for me: jsfiddle.net/5cf7bpdu Open devtools console and you'll see it's working.
-
João Eduardo about 4 yearsI'm wondering why everyone is avoiding the native buffer
toString('base64')
method. -
jvatic about 4 yearsYour answer only applies to NodeJS and will not work in the browser.
-
João Eduardo about 4 years@jvatic I see, the OP did not clearly specify the Running Environment, so my answer is not incorrect, he only tagged
Javascript
. So I updated my answer to make it more concise. I think this is an important answer because I was searching how to do this and could not get to the best answer to the problem. -
e741af0d41bc74bf854041f1fbdbf over 3 yearsAnother alternative:
btoa(Array.from(new Uint8Array(arraybuffer)).map(b => String.fromCharCode(b)).join(''))
. -
Ganesh umashankar over 3 yearshow do you reverse this back to bytes array?
-
se22as over 3 yearsThis is the only solution i have found that worked for me.
-
Larry K about 3 yearsI think you also need to remove the DataURL header (
data:*/*;base64,
) to obtain just the Base64 string. See MDN docs -
Andrew about 3 years@JoãoEduardoSoareseSilva because not everyone is using Node - Node's
Buffer
doesn't exist in the browser. -
João Eduardo about 3 years@Andrew After I got better context to this question I learned that, I provided my own answer for Node users on this question, the issue is that this question is so popular that it overshadows the results for people that are using Node.
-
cancerbero about 3 yearsThis is the correct answer when btoa or Buffer are not available (react-native)
-
fjsj almost 3 yearsbest answer for me since includes the decoding
-
RouR over 2 yearsFailed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range
-
AMDI about 2 yearsI tried with "_arrayBufferToBase64" method and first time its uploading fine for 600MB and again i tried to upload 150MB file, browser is throwing "out of memory" page. Please let me now how can we avoid this or is there any limit to size or above method is storing in browser cache.
-
Xunnamius almost 2 yearsHello from 2022 in Firefox. So it seems like Alex and @cuixiping's solutions are the fastest and most preferred as of 2022?
-
Nikolay Makhonin almost 2 yearsbtoa converts array to string before converting it to base64