Base64 in JavaScript
JavaScript provides built-in functions for Base64 encoding, but there are important nuances to understand.
Built-in Functions
// Encoding
const encoded = btoa("Hello"); // "SGVsbG8="
// Decoding
const decoded = atob("SGVsbG8="); // "Hello"
The Unicode Problem
btoa() only works with ASCII characters. For Unicode text, you need extra steps:
// Encoding Unicode
function encodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(
/%([0-9A-F]{2})/g,
(_, p1) => String.fromCharCode('0x' + p1)
));
}
// Decoding Unicode
function decodeUnicode(str) {
return decodeURIComponent(atob(str).split('').map(
c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join(''));
}
Modern Approach with TextEncoder
// Encoding with TextEncoder (handles Unicode properly)
function toBase64(str) {
const bytes = new TextEncoder().encode(str);
const binString = Array.from(bytes, b =>
String.fromCodePoint(b)
).join("");
return btoa(binString);
}
// Decoding
function fromBase64(base64) {
const binString = atob(base64);
const bytes = Uint8Array.from(binString, c =>
c.codePointAt(0)
);
return new TextDecoder().decode(bytes);
}
Working with Files
// Convert File to Base64
async function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
});
}
// Usage
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
const base64 = await fileToBase64(e.target.files[0]);
console.log(base64); // "data:image/png;base64,iVBORw0..."
});