Toolypet
Back to Blog
Dev

Base64 编码完全指南:从原理到应用

了解 Base64 编码的工作原理以及在 Web 开发中的实用应用方法。

Toolypet Team4 min read
Base64 编码完全指南:从原理到应用

Base64 为什么被创造出来?

要理解 Base64 的诞生背景,需要回溯到1970年代的电子邮件系统。当时的电子邮件协议 SMTP 只能传输 7 位 ASCII 字符。只支持英文字母、数字和基本符号,不仅无法传输图片或文档等二进制文件,甚至连中文等多字节字符都无法传输。

为了解决这个问题,MIME(Multipurpose Internet Mail Extensions)标准被开发出来,其核心技术之一就是 Base64。Base64 可以将任何二进制数据转换为安全的 ASCII 字符串,这样即使在只能处理文本的系统中也能传输文件。

时至今日,Base64 仍然被广泛使用。你可以在电子邮件附件、网页的内联图片、API 认证、JWT 令牌等各种场景中遇到它。这是 Web 开发者必须理解的基础知识。

Base64 的核心原理:64 个安全字符

Base64 这个名字源于使用 64 个字符。这 64 个字符是经过精心挑选的,能够在全球几乎所有系统中安全处理:

A-Z (26个) + a-z (26个) + 0-9 (10个) + + / (2个) = 64 个字符

另外还使用 = 字符用于填充。为什么是 64 个?因为 64 是 2^6,所以可以用 6 位表示一个 Base64 字符。计算机处理数据的单位字节(8位)与 6 位之间的关系是 Base64 算法的核心。

编码过程:逐步理解

让我们以 "Man" 这个字符串为例,看看 Base64 编码是如何工作的。

第1步:将每个字符转换为 8 位二进制数

M → 77  → 01001101
a → 97  → 01100001
n → 110 → 01101110

第2步:将 24 位分成 4 个 6 位组

将 24 位(3字节)按 6 位分割得到 4 个组。这就是 Base64 将数据大小增加约 33% 的原因。3 字节输入转换为 4 字符(4字节)输出。

010011 | 010110 | 000101 | 101110

第3步:将每个 6 位转换为 Base64 字符

010011 → 19 → T
010110 → 22 → W
000101 → 5  → F
101110 → 46 → u

结果:"Man""TWFu"

填充(=)的作用

如果输入数据不是 3 字节的倍数会怎样?这时就会使用填充字符 =

例如只编码 "M"(1字节)时:

  • 将 8 位按 6 位单位分割,会剩余 2 位
  • 添加 4 位的 0,创建 2 个 Base64 字符
  • 剩余的 2 个位置用 = 填充
"M" → "TQ=="
"Ma" → "TWE="
"Man" → "TWFu"

填充使解码时能够知道原始数据的确切长度。不过在 URL 中使用时有时会省略填充。

Web 开发中的实战应用

1. 使用 Data URI 内联图片

使用 Data URI 可以将图片直接包含在 HTML 或 CSS 中,无需单独的文件。

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..." />
.icon {
  background-image: url('data:image/svg+xml;base64,PHN2Zy...');
}

适合使用的情况:

  • 小图标(1-2KB 以下)
  • 不会重复使用的图片
  • 需要减少 HTTP 请求数的情况

应避免的情况:

  • 大图片(33% 容量增加会成为负担)
  • 在多个页面使用相同图片(无法缓存)
  • 图片经常变更

2. HTTP Basic 认证

HTTP Basic 认证是最简单的认证方式之一。将用户名和密码用冒号连接后进行 Base64 编码。

const username = 'admin';
const password = 'secret123';
const credentials = btoa(`${username}:${password}`);

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

服务器会解码这个头部来提取认证信息。但是,由于 Base64 不是加密,必须与 HTTPS 一起使用。如果通过 HTTP 传输,任何人都可以看到密码。

3. JWT(JSON Web Token)结构

JWT 由三部分组成,每部分都使用 Base64URL 编码:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.  // 头部
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4ifQ.  // 载荷
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c  // 签名

JWT 使用 Base64URL 的原因是令牌可能作为 URL 的查询参数传递。标准 Base64 的 +/ 在 URL 中有特殊含义,所以要替换为安全的字符。

4. 文件上传

用 Ajax 上传文件时,有时会以 Base64 字符串而不是 FormData 方式传输:

const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
const reader = new FileReader();

reader.onload = function(e) {
  const base64 = e.target.result;
  // 发送到服务器
  fetch('/upload', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ file: base64 })
  });
};

reader.readAsDataURL(file);

这种方式便于与 JSON API 一起使用,但由于文件大小会增加 33%,不适合大文件。

各编程语言的用法

JavaScript (浏览器)

// 编码
const encoded = btoa('Hello World');  // "SGVsbG8gV29ybGQ="

// 解码
const decoded = atob('SGVsbG8gV29ybGQ=');  // "Hello World"

注意:btoa()atob() 只支持拉丁字符。要处理中文或表情符号:

// UTF-8 编码
function encodeUnicode(str) {
  return btoa(encodeURIComponent(str).replace(
    /%([0-9A-F]{2})/g,
    (_, p1) => String.fromCharCode('0x' + p1)
  ));
}

// UTF-8 解码
function decodeUnicode(str) {
  return decodeURIComponent(
    atob(str).split('').map(c =>
      '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
    ).join('')
  );
}

Node.js

// 编码
const encoded = Buffer.from('Hello World').toString('base64');

// 解码
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');

Python

import base64

# 编码
encoded = base64.b64encode(b'Hello World').decode('utf-8')

# 解码
decoded = base64.b64decode('SGVsbG8gV29ybGQ=').decode('utf-8')

# URL-safe Base64
url_safe = base64.urlsafe_b64encode(b'data').decode('utf-8')

Base64 vs Base64URL 对比

特性Base64Base64URL
+ 字符+- (连字符)
/ 字符/_ (下划线)
填充 =必需可选(可省略)
主要用途电子邮件、一般数据URL、文件名、JWT

在 URL 中,+ 可能被解释为空格,/ 可能被解释为路径分隔符。Base64URL 可以防止这些问题。

常见错误和注意事项

1. 把 Base64 误认为加密 Base64 是编码而非加密。任何人都可以轻松解码,所以不能用于隐藏敏感信息。如果需要安全性,请使用 AES 等真正的加密算法。

2. 对大文件使用 Data URI Data URI 无法缓存。将 100KB 图片转换为 Base64 会变成 133KB,每次页面加载都会重复下载。如果分离为外部文件,可以享受浏览器缓存的好处。

3. 忽略换行符 某些 Base64 实现会每 76 个字符插入换行(MIME 标准)。如果解码前不移除换行,可能会发生错误。

4. 忽略字符编码 直接用 btoa() 编码中文会报错。需要先转换为 UTF-8。

Toolypet Base64 工具使用

Toolypet 的 Base64 编码器/解码器简化了开发者的工作流程:

  • 文本转换:即时将普通文本转换为 Base64,或反向转换
  • 文件转换:拖放即可将图片或文档转换为 Base64
  • Data URI 生成:自动生成包含适当 MIME 类型的 Data URI
  • UTF-8 自动处理:完美支持中文、表情符号等 Unicode 字符

在开发中需要 Base64 转换时,无需安装额外库或编写代码,直接在浏览器中使用即可。

Base64EncodingBinary DataWeb Development