Uint8Array.prototype.setFromBase64()
The setFromBase64()
method of Uint8Array
instances populates this Uint8Array
object with bytes from a base64-encoded string, returning an object indicating how many bytes were read and written.
This method is most suitable for populating a pre-allocated array buffer. If you just want to create a new Uint8Array
object from a base64-encoded string, use the static method Uint8Array.fromBase64()
instead.
Syntax
setFromBase64(string)
setFromBase64(string, options)
Parameters
string
-
A base64 string encoding bytes to write into a
Uint8Array
. It has the same requirements as thestring
parameter ofUint8Array.fromBase64()
. Note that the string is only read up to the point where the array is filled, so any invalid base64 syntax after that point is ignored. options
Optional-
An object customizing the base64 string interpretation process. It has the same requirements as the
options
parameter ofUint8Array.fromBase64()
.
Return value
An object containing the following properties:
read
-
The number of base64 characters read from the input string. If the decoded data fits into the array, this is the length of the input string (including padding); otherwise, it is the length up to the last complete 4-character chunk that fits into the array. Chunks will never be split (because the remaining bits cannot be partially "put back" into the base64 without completely re-encoding it); if the next chunk cannot fit into the remainder of the array, it will be entirely unread, resulting in the last one or two bytes of the array not being written.
written
-
The number of bytes written to the
Uint8Array
. Will never be greater than thisUint8Array
'sbyteLength
.
Exceptions
SyntaxError
-
Thrown if the input string contains characters outside the specified alphabet, or if the last chunk does not satisfy the
lastChunkHandling
option. TypeError
-
Thrown in one of the following cases:
- The input string is not a string.
- The
options
object is not an object orundefined
. - The options are not of the expected values or
undefined
.
Examples
Decoding a base64 string
This example uses the default alphabet
and lastChunkHandling
options to decode a base64 string into an existing Uint8Array
.
const uint8Array = new Uint8Array(16);
const result = uint8Array.setFromBase64("PGI+ TURO PC9i Pg==");
console.log(result); // { read: 19, written: 10 }
console.log(uint8Array);
// Uint8Array(16) [60, 98, 62, 77, 68, 78, 60, 47, 98, 62, 0, 0, 0, 0, 0, 0]
Decoding a big string into a small array
If the string contains more data than the array can hold, the method will only write as many bytes as the array can hold, without discarding any bits.
const uint8Array = new Uint8Array(8);
const result = uint8Array.setFromBase64("PGI+ TURO PC9i Pg==");
console.log(result); // { read: 9, written: 6 }
console.log(uint8Array);
// Uint8Array(8) [60, 98, 62, 77, 68, 78, 0, 0]
Note how the last two bytes of the array are not written. To decode these two bytes, we need to read at least three more base64 characters, which represent 18 bits. These can't fit into the remaining two bytes of the array, so we can only write 2 chunks, or 6 bytes.
Setting data at a specific offset
The setFromBase64()
method always starts writing at the beginning of the Uint8Array
. If you want to write to the middle of the array, you can write to a TypedArray.prototype.subarray()
instead.
const uint8Array = new Uint8Array(16);
// Start writing at offset 2
const result = uint8Array.subarray(2).setFromBase64("PGI+ TURO PC9i Pg==");
console.log(result); // { read: 19, written: 10 }
console.log(uint8Array);
// Uint8Array(16) [0, 0, 60, 98, 62, 77, 68, 78, 60, 47, 98, 62, 0, 0, 0, 0]
Stream decoding
This example is adapted from the original proposal. It mimics the TextDecoder
API with the stream
option. Note the use of lastChunkHandling: "stop-before-partial"
to handle incomplete chunks.
class Base64Decoder {
#extra = "";
decode(chunk = "", options = {}) {
const opts = { ...options };
// match TextEncoder API
if (opts.stream) {
opts.lastChunkHandling = "stop-before-partial";
}
chunk = this.#extra + chunk;
this.#extra = "";
// For simplicity, allocate new memory every time
// the calculation below is guaranteed to be enough,
// but may be too much if there is whitespace
// if you're really concerned about memory, a TextDecoder style API is a bad choice
let buffer = new Uint8Array(Math.ceil((chunk.length * 3) / 4));
const { read, written } = buffer.setFromBase64(chunk, opts);
buffer = buffer.subarray(0, written);
this.#extra = chunk.slice(read);
return buffer;
}
}
const decoder = new Base64Decoder();
console.log(decoder.decode("SG Vsb ", { stream: true }));
// Uint8Array(3) [72, 101, 108]
console.log(decoder.decode("G8gV29ybGR ", { stream: true }));
// Uint8Array(6) [108, 111, 32, 87, 111, 114]
console.log(decoder.decode(""));
// Uint8Array(2) [108, 100]
Specifications
Specification |
---|
Uint8Array to/from base64 # sec-uint8array.prototype.setfrombase64 |
Browser compatibility
BCD tables only load in the browser