2

Given a base64 string, what is the safest and most efficient way to create an ArrayBuffer. Specifically a typeless array buffer in pure modern JavaScript.

The first SO result is this question from 2014. The accepted answer is

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

It already assumes a type and there are comments which suggest that this is not always correct.

Is this still the best solution today? Do we have to iterate over all elements in a for loop? Is there a better and more efficient way using vanilla JS where we can pass a blob of the string?

An example problem is processing a GLTF buffer which is provided as a base64 encoded string:

let str = 'data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=';

This has two separate views of scalar (unsigned short) and vec3 (float) data, requiring further processing.

[edit]

So the most popular answer is not of use here as it creates a TypedArray but the data in the base64 string does not represent a homogenous data set.

asked Nov 13, 2021 at 18:04
2
  • Your last line makes no sense at all. Is that left over from another post? Nowhere in your question is there anything about views, unsigned short, vec3 or float, and none of those things would seem to be Javascript concepts. Commented Nov 13, 2021 at 18:24
  • @TimRoberts The last line is to add context. The issue is that the most popular answer creates a Uint8Array and not a typeless ArrayBuffer on which further operations can be made. It's really to iterate that I don't want a TypedArray because that will lock you into a single view of the binary data. Commented Nov 13, 2021 at 18:31

1 Answer 1

5

Since your str is a data:uri, you might use fetch:

let str = 'data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=';
fetch(str)
 .then(b => b.arrayBuffer())
 .then(buff => console.log( new Int8Array(buff) /* just for a view purpose */ ))
 .catch(e => console.log(e))

answered Nov 13, 2021 at 18:55

4 Comments

Is the .then(r => r.blob()) step necessary? Can we use arrayBuffer() immediately?
Fetch response seems to have an arrayBuffer() method for convenience. Is there a difference between these two? developer.mozilla.org/en-US/docs/Web/API/Response/arrayBuffer
@dubious, you're right! No need to blob()
This works (although using the await pattern would be more modern) but be aware that this is subject to the content security policy

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.