Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Encode an ArrayBuffer as a base64 string
// Converts an ArrayBuffer directly to base64, without any intermediate 'convert to string then
// use window.btoa' step. According to my tests, this appears to be a faster approach:
// http://jsperf.com/encoding-xhr-image-data/5
function base64ArrayBuffer(arrayBuffer) {
var base64 = ''
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
var bytes = new Uint8Array(arrayBuffer)
var byteLength = bytes.byteLength
var byteRemainder = byteLength % 3
var mainLength = byteLength - byteRemainder
var a, b, c, d
var chunk
// Main loop deals with bytes in chunks of 3
for (var i = 0; i < mainLength; i = i + 3) {
// Combine the three bytes into a single integer
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
// Use bitmasks to extract 6-bit segments from the triplet
a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
d = chunk & 63 // 63 = 2^6 - 1
// Convert the raw binary segments to the appropriate ASCII encoding
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
}
// Deal with the remaining bytes and padding
if (byteRemainder == 1) {
chunk = bytes[mainLength]
a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
// Set the 4 least significant bits to zero
b = (chunk & 3) << 4 // 3 = 2^2 - 1
base64 += encodings[a] + encodings[b] + '=='
} else if (byteRemainder == 2) {
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
// Set the 2 least significant bits to zero
c = (chunk & 15) << 2 // 15 = 2^4 - 1
base64 += encodings[a] + encodings[b] + encodings[c] + '='
}
return base64
}
@tsenart

I kind of need the reverse. A base64 encoded utf8 string to an ArrayBuffer. How can I do that?

@jonleighton
Owner

I guess you would need to write this function sort of in reverse. So iterate over each 4 characters, converting them to three bytes which you append to the ArrayBuffer, and then with special handling for the padding at the end. I don't have code for that though :)

@n1k0

As you just saved my life, I just wanted to say THANK YOU

@joscha

kinda late, but here is the reverse

@joscha

And CryptoJS has a method to transform to a WordArray as well: CryptoJS.enc.Base64.parse

@tonikitoo

@joscha, the "reverse" (see comment https://gist.github.com/jonleighton/958841/#comment-733469) seems to be 3x slower than atob in my tests.

@sparrowprince

This is a pretty nifty method! Is there any chance you might add a license to it? I would really like to include it in a project of mine but am not allowed to do so without a proper license ;-)

@lapsio

It's amazing, I'm working on >10 000 000 arrays (audio files) and performance was serious bottleneck, thanks

@ketting00

This function is flaw. Everything turns out as "AAAAAAAAA" for small number like [0.000354254885, -0.521365849254, 0.002453687924].

@gfranko

Thank you very much, works like a charm! Would you mind adding a license to this?

@hogetsuyoshi

Thank you for this useful script. Which license is this? GPL? BSD?

@andreagulino

You made my day.

@yamaneko1212

You are my hero!

@GeorgeGardiner

Boom, thanks.

@mrmaffen

Thanks a lot! Would be awesome if you could state under which license you published this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.