🔐
← 返回教程列表

在 JavaScript 中进行 Base64 编码/解码:btoa()、atob() 和 Unicode

· 标签: javascript, base64, btoa, atob, nodejs, encoding, web-development

在 JavaScript 中进行 Base64 编码和解码

JavaScript 提供了多种内置方式来编码和解码 Base64 字符串。无论你是在构建浏览器应用还是 Node.js 服务器,理解如何使用 Base64 对于在 JSON、HTML 和 URL 等基于文本的格式中处理二进制数据都至关重要。

在浏览器中使用 btoa() 和 atob()

浏览器 JavaScript 中用于 Base64 的两个核心函数是 btoa()atob()。这些函数名遵循一种较旧的命名约定——btoa 代表 "binary to ASCII"(二进制转 ASCII),atob 代表 "ASCII to binary"(ASCII 转二进制)。它们已被所有主流浏览器支持数十年。

使用 btoa() 编码

const originalString = 'Hello, world!';
const encoded = btoa(originalString);
console.log(encoded);
// 输出:SGVsbG8sIHdvcmxkIQ==

使用 atob() 解码

const base64String = 'SGVsbG8sIHdvcmxkIQ==';
const decoded = atob(base64String);
console.log(decoded);
// 输出:Hello, world!

这两个函数都只适用于包含 Latin-1 字符(每个字符由单个字节表示)的字符串。这是一个重要的限制,我们将在下一节中讨论。

处理 Unicode 和非 ASCII 字符

一个常见的陷阱:btoa() 在收到包含 Latin-1 范围之外字符(如表情符号、中文字符或带重音字母)的字符串时会抛出错误。

btoa('Hello 你好');
// 错误:要编码的字符串包含 Latin-1 范围之外的字符。

要编码 Unicode 字符串,你需要先将字符串转换为字节,然后再编码这些字节。现代方法是使用 TextEncoderTextDecoder API:

function unicodeToBase64(str) {
  const bytes = new TextEncoder().encode(str);
  const binaryString = String.fromCharCode(...bytes);
  return btoa(binaryString);
}

function base64ToUnicode(base64) {
  const binaryString = atob(base64);
  const bytes = Uint8Array.from(binaryString, (c) => c.charCodeAt(0));
  return new TextDecoder().decode(bytes);
}

// 用法
const encoded = unicodeToBase64('Hello 你好 🚀');
console.log(encoded);
// 输出:SGVsbG8g5L2g5aW9IPCfj4A=

const decoded = base64ToUnicode(encoded);
console.log(decoded);
// 输出:Hello 你好 🚀

一种较旧的技术使用 encodeURIComponentdecodeURIComponent,但 TextEncoder/TextDecoder 方法更稳健,是推荐的现代解决方案。

编码二进制数据(ArrayBuffer)

当处理来自 fetchFileReader 等 API 的文件、图片或原始二进制数据时,你通常会得到一个 ArrayBufferUint8Array。以下是如何将其转换为 Base64:

function arrayBufferToBase64(buffer) {
  const bytes = new Uint8Array(buffer);
  let binaryString = '';
  for (let i = 0; i < bytes.length; i++) {
    binaryString += String.fromCharCode(bytes[i]);
  }
  return btoa(binaryString);
}

function base64ToArrayBuffer(base64) {
  const binaryString = atob(base64);
  const bytes = new Uint8Array(binaryString.length);
  for (let i = 0; i < binaryString.length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return bytes.buffer;
}

在浏览器中将文件转换为 Base64

以下是一个使用 FileReader 将用户选择的文件转换为 Base64 data URL 的完整示例:

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

// 与文件输入一起使用
document.querySelector('input[type="file"]').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  try {
    const dataUrl = await fileToBase64(file);
    console.log(dataUrl); // data:image/png;base64,iVBORw0KGgo...
  } catch (err) {
    console.error('转换失败:', err);
  }
});

在 Node.js 中使用 Base64

Node.js 提供了 Buffer 类用于 Base64 操作,它比浏览器的 btoa/atob 更灵活。Buffer 类自动处理编码和解码,包括 Unicode,并支持多种编码格式。

基本编码和解码

// 将字符串编码为 Base64
const encoded = Buffer.from('Hello, world!').toString('base64');
console.log(encoded);
// 输出:SGVsbG8sIHdvcmxkIQ==

// 将 Base64 字符串解码回文本
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded);
// 输出:Hello, world!

Node.js 中的 Unicode 支持

与浏览器中的 btoa() 不同,Node.js 的 Buffer 可以无缝处理 Unicode:

const encoded = Buffer.from('Hello 你好 🚀').toString('base64');
console.log(encoded);
// 输出:SGVsbG8g5L2g5aW9IPCfj4A=

const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded);
// 输出:Hello 你好 🚀

读取文件并编码为 Base64

const fs = require('fs');

// 读取文件并将其编码为 Base64
const buffer = fs.readFileSync('image.png');
const base64 = buffer.toString('base64');
const dataUrl = `data:image/png;base64,${base64}`;

Node.js 中的 Base64url 编码

Node.js 15.7.0+ 支持原生的 Base64url 编码,它会将 + 替换为 -/ 替换为 _,并省略填充:

const encoded = Buffer.from('Hello, world!').toString('base64url');
console.log(encoded);
// 输出:SGVsbG8sIHdvcmxkIQ (无填充)

const decoded = Buffer.from(encoded, 'base64url').toString('utf-8');
console.log(decoded);
// 输出:Hello, world!

性能注意事项

对于大型数据,重复的 Base64 操作可能会很慢。以下是一些建议:

  • 对于 Unicode 字符串,使用 TextEncoder/TextDecoder 而非手动转换
  • 在 Node.js 中,Buffer.from() 经过高度优化——优先使用它而不是手动实现
  • 除非必要,避免将大型文件转换为 Base64(考虑使用流式处理)
  • 对于大型数据集,考虑在浏览器中使用 BlobFileReader,以避免阻塞主线程

在线尝试 Base64 编码

使用我们的免费在线 Base64 编码器和解码器,直接在浏览器中试验编码和解码。无需编写代码——只需粘贴文本或上传文件,即可立即获得 Base64 结果。