第六章

JavaScript 中的 Base64

前端开发必读:btoa、atob 与中文乱码解决方案

6.1 基础函数:btoa 和 atob

浏览器提供了两个原生的全局函数:

  • btoa(): Binary to ASCII (编码)
  • atob(): ASCII to Binary (解码)
// 编码
const original = "Hello, World!";
const encoded = btoa(original);
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="

// 解码
const decoded = atob(encoded);
console.log(decoded); // "Hello, World!"

❗ 重要限制:

btoa() 仅支持 ASCII 字符(0-255)。如果字符串包含中文或 emoji,会直接报错:InvalidCharacterError

6.2 处理中文(Unicode 字符)

为了支持中文,我们需要先对字符串进行 UTF-8 编码及其转义。一个经典的跨浏览器解决方案是:

// 编码 Unicode
function encodeUtf8ToBase64(str) {
    return btoa(unescape(encodeURIComponent(str)));
}

// 解码 Unicode
function decodeBase64ToUtf8(base64) {
    return decodeURIComponent(escape(atob(base64)));
}

// 测试
const text = "你好,世界 🌍";
const encoded = encodeUtf8ToBase64(text);
console.log(encoded); // "5L2g5aW977yM5LiW55WMIPCfjI0="
console.log(decodeBase64ToUtf8(encoded)); // "你好,世界 🌍"

6.3 现代 API:FileReader

在处理文件上传或图片预览时,使用 FileReader 是更现代、更强大的方式。

function fileToBase64(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
    });
}

// 在 input type="file" 的 change 事件中使用
document.getElementById('fileInput').addEventListener('change', async (e) => {
    const file = e.target.files[0];
    const base64 = await fileToBase64(file);
    console.log(base64); // "data:image/png;base64,iVBORw0KGgo..."
});