首页 / 博客 / JavaScript Base64 解码

JavaScript Base64 解码完全指南 2026

最后更新:2026年5月16日 · 阅读约10分钟

Base64 编码无处不在 — 从在 HTML 中嵌入图片到 API 中传输二进制数据。做 JavaScript 开发,掌握 Base64 编解码是基本功。这篇指南从基础的 atob/btoa 函数讲起,覆盖 Unicode 文本处理、二进制数据,以及浏览器和 Node.js 的区别。

快速提示:现在就想解码 Base64?试试我们的免费 在线 Base64 编解码工具 — 粘贴文本立即解码,无需注册。

基础:atob 和 btoa

JavaScript 在浏览器端提供了两个内置函数:

// 编码
const encoded = btoa("Hello World");
console.log(encoded); // "SGVsbG8gV29ybGQ="

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

看起来很简单。但有个坑 — btoa()atob() 只能正确处理 Latin1(ASCII)字符。试试编码中文或 emoji,直接报错。

Unicode 问题

btoa 处理非 ASCII 文本会怎样:

// 直接报错!
try {
    btoa("你好世界");
} catch (e) {
    console.error(e.message);
    // "Failed to execute 'btoa': The string to be encoded contains characters outside of the Latin1 range."
}

btoa/atob 只能处理 0x00–0xFF 范围的字符。要完整支持 Unicode,需要换一种方式。

Unicode 的 Base64:TextEncoder 和 TextDecoder

现代方案是用 TextEncoderTextDecoder 在字符串和字节数组之间转换,再配合 Base64 转换:

// Unicode 字符串编码为 Base64
function encodeBase64(str) {
    const encoder = new TextEncoder();
    const bytes = encoder.encode(str);
    let binary = '';
    bytes.forEach(byte => binary += String.fromCharCode(byte));
    return btoa(binary);
}

// Base64 解码为 Unicode 字符串
function decodeBase64(base64) {
    const binary = atob(base64);
    const bytes = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
        bytes[i] = binary.charCodeAt(i);
    }
    const decoder = new TextDecoder();
    return decoder.decode(bytes);
}

// 现在支持 Unicode 了!
const encoded = encodeBase64("你好世界 🌍");
console.log(encoded); // "5L2g5aW95LiW55WJIPCfjI0="

const decoded = decodeBase64("5L2g5aW95LiW55WJIPCfjI0=");
console.log(decoded); // "你好世界 🌍"

更简洁的写法

也可以用展开运算符写得更简洁:

// 简洁编码
function toBase64(str) {
    return btoa(String.fromCharCode(...new TextEncoder().encode(str)));
}

// 简洁解码
function fromBase64(b64) {
    return new TextDecoder().decode(
        Uint8Array.from(atob(b64), c => c.charCodeAt(0))
    );
}

console.log(toBase64("Hello 你好")); // "SGVsbG8g5L2g5aW9"
console.log(fromBase64("SGVsbG8g5L2g5aW9")); // "Hello 你好"

注意:展开运算符的方式(...new TextEncoder().encode(str))在处理超大字符串(10万+字符)时可能触发最大调用栈限制。大数据量用循环方式更稳。

处理二进制数据

文件编码为 Base64

在浏览器中处理文件时,经常需要把 FileBlob 转成 Base64:

// 用 FileReader(回调方式)
function fileToBase64(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => {
            // result 是 data URL,如 "data:image/png;base64,iVBOR..."
            const base64 = reader.result.split(',')[1];
            resolve(base64);
        };
        reader.onerror = reject;
        reader.readAsDataURL(file);
    });
}

// 使用
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async (e) => {
    const file = e.target.files[0];
    const base64 = await fileToBase64(file);
    console.log(base64);
});

用 arrayBuffer 的现代方式

// 用 arrayBuffer(现代、基于 Promise)
async function fileToBase64Modern(file) {
    const buffer = await file.arrayBuffer();
    const bytes = new Uint8Array(buffer);
    let binary = '';
    bytes.forEach(byte => binary += String.fromCharCode(byte));
    return btoa(binary);
}

Base64 转回 Blob

function base64ToBlob(base64, mimeType = 'application/octet-stream') {
    const binary = atob(base64);
    const bytes = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
        bytes[i] = binary.charCodeAt(i);
    }
    return new Blob([bytes], { type: mimeType });
}

// 创建下载链接
const blob = base64ToBlob("SGVsbG8gV29ybGQ=", "text/plain");
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'hello.txt';
a.click();
URL.revokeObjectURL(url);

Node.js 中的 Base64

Node.js 没有全局的 atob/btoa(Node 16+ 才加了)。标准做法是用 Buffer

用 Buffer 编码

// 字符串编码为 Base64
const str = "Hello World 你好";
const encoded = Buffer.from(str, 'utf-8').toString('base64');
console.log(encoded); // "SGVsbG8gV29ybGQg5L2g5aW9"

// Base64 解码为字符串
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded); // "Hello World 你好"

Node.js 中处理文件

const fs = require('fs');

// 读取文件编码为 Base64
const fileBuffer = fs.readFileSync('image.png');
const base64 = fileBuffer.toString('base64');
console.log(base64);

// Base64 解码写入文件
const decoded = Buffer.from(base64, 'base64');
fs.writeFileSync('output.png', decoded);

Node.js 16+ 的 atob/btoa

// Node 16+ 有全局 atob/btoa
const encoded = btoa("Hello World");
console.log(encoded); // "SGVsbG8gV29ybGQ="

const decoded = atob("SGVsbG8gV29ybGQ=");
console.log(decoded); // "Hello World"

注意:Node.js 的 atob/btoa 和浏览器版一样有 Latin1 限制。处理 Unicode 还是用 Buffer 靠谱。

浏览器 vs Node.js:关键区别

// 通用写法(浏览器和 Node.js 18+ 都能用)
function universalEncode(str) {
    const bytes = new TextEncoder().encode(str);
    let binary = '';
    bytes.forEach(byte => binary += String.fromCharCode(byte));
    return btoa(binary);
}

function universalDecode(b64) {
    const binary = atob(b64);
    const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
    return new TextDecoder().decode(bytes);
}

URL 安全的 Base64

标准 Base64 中的 +/ 在 URL 里有特殊含义。URL 安全的 Base64 会替换它们:

// 标准 Base64 转 URL 安全
function base64ToUrlSafe(base64) {
    return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

// URL 安全转回标准 Base64
function urlSafeToBase64(urlSafe) {
    let base64 = urlSafe.replace(/-/g, '+').replace(/_/g, '/');
    // 补齐填充
    while (base64.length % 4) base64 += '=';
    return base64;
}

const encoded = btoa("Hello+World/Test");
const urlSafe = base64ToUrlSafe(encoded);
console.log(urlSafe); // "SGVsbG8rV29ybGQvVGVzdA"

const restored = urlSafeToBase64(urlSafe);
console.log(atob(restored)); // "Hello+World/Test"

常见使用场景

图片的 Data URL

// 从 Base64 创建 data URL
const base64Image = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";
const dataUrl = `data:image/png;base64,${base64Image}`;

// 用在 img 标签中
const img = document.createElement('img');
img.src = dataUrl;
document.body.appendChild(img);

HTTP Basic 认证

// 创建 Basic Auth 请求头
const username = "admin";
const password = "secret";
const credentials = btoa(`${username}:${password}`);

fetch('/api/data', {
    headers: {
        'Authorization': `Basic ${credentials}`
    }
});

localStorage 存储数据

// 把复杂数据存为 Base64
const data = { theme: "dark", lang: "zh-CN" };
const json = JSON.stringify(data);
const encoded = btoa(unescape(encodeURIComponent(json)));
localStorage.setItem('settings', encoded);

// 读取
const stored = localStorage.getItem('settings');
const decoded = decodeURIComponent(escape(atob(stored)));
const settings = JSON.parse(decoded);

错误处理

// 安全的 Base64 解码
function safeDecodeBase64(base64) {
    try {
        // 验证 Base64 格式
        if (!/^[A-Za-z0-9+/]*={0,2}$/.test(base64)) {
            throw new Error('无效的 Base64 格式');
        }
        return atob(base64);
    } catch (e) {
        console.error('Base64 解码失败:', e.message);
        return null;
    }
}

// 测试
console.log(safeDecodeBase64("SGVsbG8=")); // "Hello"
console.log(safeDecodeBase64("not-valid!")); // null

常见问题

atob 和 btoa 有什么区别?

btoa() 把字符串编码成 Base64(binary to ASCII)。atob() 把 Base64 字符串解码回来(ASCII to binary)。它们是互逆操作。

为什么 btoa 处理中文会报错?

btoa() 只支持 Latin1 字符(0x00–0xFF)。处理 Unicode 文本需要先用 TextEncoder 转成字节再编码。参考上面的 Unicode 部分。

如何在 JavaScript 中把文件编码为 Base64?

浏览器端用 FileReader.readAsDataURL()file.arrayBuffer() 配合 btoa()。Node.js 用 fs.readFileSync('file').toString('base64')

浏览器和 Node.js 的 Base64 一样吗?

编码算法一样,但 API 不同。浏览器用 atob/btoa,Node.js 用 Buffer。写同构代码用 TextEncoder/TextDecoder

什么是 URL 安全的 Base64?

标准 Base64 中的 +/ 在 URL 里是保留字符。URL 安全的 Base64 把 + 换成 -/ 换成 _,并去掉填充的 =

如何在 Node.js 中解码 Base64?

字符串用 Buffer.from(base64String, 'base64').toString('utf-8'),原始二进制数据用 Buffer.from(base64String, 'base64')

在线试试

不想写代码来编解码 Base64?试试我们的 免费在线 Base64 编解码工具 — 支持文本、文件和 Unicode。在浏览器中运行,无需上传服务器。