← 返回博客

JavaScript 中 Base64 编解码完整指南

2026-04-05 · 5 分钟阅读

← 返回博客

JavaScript 中 Base64 编解码完整指南

· 5 分钟阅读

浏览器内置方法:btoa 和 atob

现代浏览器提供了两个全局函数用于 Base64 操作:btoa()(binary to ASCII,即编码)和 atob()(ASCII to binary,即解码)。这两个函数使用方便,无需引入任何库。

// 编码 / Encoding
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="

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

需要注意的是,btoa() 只接受 Latin-1(ISO-8859-1)字符,即每个字符的 Unicode 码点不超过 255。如果输入包含中文、表情符号或其他多字节 Unicode 字符,btoa() 会抛出 InvalidCharacterError 异常。这是初学者最常遇到的坑。

处理 Unicode 字符串

要对包含 Unicode 字符的字符串进行 Base64 编码,需要先将字符串转换为 UTF-8 字节序列,再进行 Base64 编码。现代浏览器可以使用 TextEncoder 完成这一步:

// 对 Unicode 字符串进行 Base64 编码
// Base64 encode a Unicode string
function encodeUnicode(str) {
  const bytes = new TextEncoder().encode(str);
  const binary = Array.from(bytes).map(b => String.fromCharCode(b)).join('');
  return btoa(binary);
}

// 解码 Base64 为 Unicode 字符串
// Decode Base64 to Unicode string
function decodeUnicode(base64) {
  const binary = atob(base64);
  const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
  return new TextDecoder().decode(bytes);
}

console.log(encodeUnicode('你好,世界!'));
// "5L2g5aW977yM5LiW55WM77yB"
console.log(decodeUnicode('5L2g5aW977yM5LiW55WM77yB'));
// "你好,世界!"

Node.js 中的 Base64 编解码

Node.js 没有 btoaatob(虽然较新版本已添加),传统上使用 Buffer 类来处理 Base64。Buffer 天然支持 UTF-8,不存在浏览器中 btoa 的 Unicode 限制。

// Node.js Buffer 方式
// Node.js Buffer approach

// 编码 / Encode
const text = '你好,World!';
const encoded = Buffer.from(text, 'utf8').toString('base64');
console.log(encoded);

// 解码 / Decode
const decoded = Buffer.from(encoded, 'base64').toString('utf8');
console.log(decoded); // "你好,World!"

// 编码文件为 Base64
// Encode a file to Base64
const fs = require('fs');
const fileBuffer = fs.readFileSync('./image.png');
const base64Image = fileBuffer.toString('base64');
console.log(`data:image/png;base64,${base64Image}`);

Node.js v16+ 已在全局作用域中提供 btoaatob,以保持与浏览器 API 的兼容性。但对于服务端应用,推荐仍使用 Buffer,因为它更灵活,能直接处理二进制数据流。

Base64URL 编解码

在处理 JWT Token 或需要将 Base64 放入 URL 的场景中,需要使用 Base64URL 变体。Base64URL 将 + 替换为 -,将 / 替换为 _,并去除填充字符 =。以下是浏览器中的实现:

// Base64URL 编码
// Base64URL encoding
function toBase64URL(str) {
  return btoa(str)
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
}

// Base64URL 解码
// Base64URL decoding
function fromBase64URL(base64url) {
  const base64 = base64url
    .replace(/-/g, '+')
    .replace(/_/g, '/');
  // 补全填充 / Add padding
  const padded = base64 + '=='.slice(0, (4 - base64.length % 4) % 4);
  return atob(padded);
}

在 Fetch API 中使用 Base64

在使用 Fetch API 发送 HTTP 请求时,有时需要将 Base64 数据作为请求体发送,或者解码响应中的 Base64 数据。以下示例演示如何处理这两种场景:

// 发送包含 Base64 图片的 POST 请求
// Send POST request with Base64 image
async function uploadImageAsBase64(file) {
  const reader = new FileReader();
  const base64 = await new Promise((resolve) => {
    reader.onload = (e) => resolve(e.target.result.split(',')[1]);
    reader.readAsDataURL(file);
  });

  const response = await fetch('/api/upload', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ image: base64 })
  });
  return response.json();
}

将 File 对象转换为 Base64

在浏览器中,用户通过 input[type=file] 选择的文件是一个 File 对象(Blob 的子类)。使用 FileReader API 可以将其转换为 Base64 字符串。这是前端处理文件上传并预览的常见模式:

// 将 File 转换为 Base64
// Convert File to Base64
function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result); // data URI
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// 使用示例 / Usage
const input = document.querySelector('input[type=file]');
input.addEventListener('change', async (e) => {
  const file = e.target.files[0];
  const dataURI = await fileToBase64(file);
  document.querySelector('img').src = dataURI;
});

常见错误与调试

最常见的错误是 InvalidCharacterError: The string to be encoded contains characters outside of the Latin1 range,这是因为直接对包含中文等多字节字符的字符串调用 btoa() 导致的。解决方案是使用前面介绍的 TextEncoder 方法或 encodeURIComponent 技巧。

另一个常见问题是解码后得到乱码,通常是因为原始数据使用了 UTF-8 以外的字符集编码。在这种情况下,需要使用 TextDecoder 并指定正确的字符集名称,如 new TextDecoder('gbk') 用于解码简体中文 GBK 编码的数据。

立即尝试在线工具,无需安装,免费使用。

打开工具 →

立即免费使用相关工具

免费使用 →