Base64 编码与解码:何时以及如何使用

· 12分钟阅读

目录

什么是 Base64 编码?

Base64 是一种二进制到文本的编码方案,它将二进制数据转换为 ASCII 字符串。它使用 64 个可打印字符(A-Z、a-z、0-9、+、/)加上等号(=)用于填充。"Base64"这个名称来源于使用 64 个不同字符作为基数来表示二进制数据。

Base64 的重要性在于:它允许您通过专为文本设计的系统安全传输二进制数据。在 Base64 出现之前,通过电子邮件发送图像或在 JSON 中嵌入二进制数据会导致数据损坏或系统完全崩溃。

Base64 不是加密 — 这是一个关键区别。它不提供任何安全性或混淆。任何人都可以立即解码 Base64,无需密钥或密码。它纯粹是为兼容性而非机密性设计的编码方案。

您每天都会遇到 Base64,通常在不知不觉中:

🛠️ 亲自试试: 使用我们的 Base64 编码器/解码器 在浏览器中即时编码和解码数据。

Base64 的底层工作原理

Base64 将每 3 个字节(24 位)的输入数据转换为 4 个字符(每个 6 位)。这种数学关系是 Base64 在转换为文本时保持数据完整性的基础。

让我们通过一个完整的示例来编码文本"Hi":

  1. 转换为 ASCII 字节: "Hi" 变成 72, 105
  2. 转换为二进制: 01001000 01101001(总共 16 位)
  3. 分组为 6 位块: 010010 | 000110 | 1001xx
  4. 填充不完整的组: 010010 | 000110 | 100100
  5. 映射到 Base64 字母表: S (18), G (6), k (36)
  6. 添加填充字符: SGk=

填充字符(=)表示最后一组缺少多少字节。一个 = 表示缺少一个字节,两个 = 表示缺少两个字节。

Base64 字符集

标准 Base64 编码中使用的 64 个字符经过精心选择,以确保在不同系统中普遍安全:

范围 字符
大写字母 A-Z 0-25
小写字母 a-z 26-51
数字 0-9 52-61
特殊字符 +/ 62-63
填充 = 不适用

大小权衡

由于每 3 个输入字节变成 4 个输出字符,Base64 会使数据大小增加约 33%。这是实现文本安全传输的基本权衡。

例如:

在决定 Base64 是否适合您的用例时,这种大小增加是需要考虑的重要因素。

何时使用 Base64

Base64 在二进制数据必须通过纯文本系统传递的特定场景中表现出色。了解这些用例有助于您就何时适合编码做出明智的决定。

电子邮件附件和 MIME

SMTP(简单邮件传输协议)于 1982 年设计,仅用于 7 位 ASCII 文本。当您将 PDF、图像或任何二进制文件附加到电子邮件时,它会被您的电子邮件客户端自动进行 Base64 编码。

MIME(多用途互联网邮件扩展)标准使用 Base64 作为二进制附件的主要编码方法。这确保您的文件无论通过哪些电子邮件服务器都能完整到达。

Web 开发中的 Data URL

Data URL 允许您直接在 HTML、CSS 或 JavaScript 中嵌入小文件,而不是发出单独的 HTTP 请求。这对以下情况特别有用:

Data URL 结构示例:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...

API 身份验证

HTTP 基本身份验证以 Base64 格式编码凭据。当您发送用户名和密码时,它们用冒号组合并进行 Base64 编码:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

这种编码使标头对 HTTP 传输安全,尽管凭据很容易解码(这就是为什么 HTTPS 至关重要)。

JSON 和 XML 数据传输

JSON 和 XML 是基于文本的格式,不能直接包含二进制数据。当您需要在这些格式中包含二进制内容时,Base64 编码是标准解决方案:

JWT 令牌

JSON Web Tokens 对其三个组件使用 Base64URL 编码(一种 URL 安全变体):标头、有效载荷和签名。这允许 JWT 在 URL、HTTP 标头和 cookie 中安全传输。

专业提示: 使用我们的 JWT 解码器 检查和验证 JWT 令牌。您将看到 Base64 编码的组件实时解码。

JavaScript 中的 Base64

JavaScript 提供了用于 Base64 编码和解码的内置函数,尽管它们在浏览器和 Node.js 环境中的工作方式不同。

浏览器环境

现代浏览器包含 btoa()(二进制到 ASCII)和 atob()(ASCII 到二进制)函数:

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

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

重要限制: btoa() 仅适用于包含 Latin1 范围(0-255)字符的字符串。对于 Unicode 字符串,您需要额外的步骤:

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

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

const encoded = encodeUnicode('Hello 世界');
console.log(encoded); // SGVsbG8g5LiW55WM

Node.js 环境

Node.js 使用 Buffer API 进行 Base64 操作,它可以正确处理二进制数据和 Unicode:

// 编码
const encoded = Buffer.from('Hello, World!').toString('base64');
console.log(encoded); // SGVsbG8sIFdvcmxkIQ==

// 解码
const decoded = Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString('utf8');
console.log(decoded); // Hello, World!

// 完美支持 Unicode
const unicodeEncoded = Buffer.from('Hello 世界').toString('base64');
console.log(unicodeEncoded); // SGVsbG8g5LiW55WM

在 Node.js 中编码文件

使用 Node.js 读取和编码文件非常简单:

const fs = require('fs');

// 读取并编码文件
const fileBuffer = fs.readFileSync('image.png');
const base64Image = fileBuffer.toString('base64');

// 保存编码数据
fs.writeFileSync('image.txt', base64Image);

// 解码并保存
const decodedBuffer = Buffer.from(base64Image, 'base64');
fs.writeFileSync('image-copy.png', decodedBuffer);

快速提示: 对于大文件,使用流而不是将整个文件读入内存。这可以防止多兆字节文件的内存问题。

Python 中的 Base64

Python 的 base64 模块提供了全面的编码和解码功能,并具有出色的 Unicode 支持。

基本编码和解码

import base64

# 编码字符串
text = "Hello, World!"
encoded = base64.b64encode(text.encode('utf-8'))
print(encoded)  # b'SGVsbG8sIFdvcmxkIQ=='

# 解码
decoded = base64.b64decode(encoded).decode('utf-8')
print(decoded)  # Hello, World!

# Unicode 无缝工作
unicode_text = "Hello 世界"
encoded_unicode = base64.b64encode(unicode_text.encode('utf-8'))
print(encoded_unicode)  # b'SGVsbG8g5LiW55WM'

处理文件

Python 使文件编码和解码变得简单:

import base64

# 编码文件
with open('image.png', 'rb') as file:
    encoded = base64.b64encode(file.read())
    
with open('image.txt', 'wb') as file:
    file.write(encoded)

# 解码文件
with open('image.txt', 'rb') as file:
    decoded = base64.b64decode(file.read())
    
with open('image-copy.png', 'wb') as file:
    file.write(decoded)

URL 安全编码

Python 包含 URL 安全的 Base64 变体,可替换有问题的字符:

import base64

text = "Hello, World!"
encoded_bytes = text.encode('utf-8')

# 标准 Base64
standard = base64.b64encode(encoded_bytes)
print(standard)  # b'SGVsbG8sIFdvcmxkIQ=='

# URL 安全 Base64(将 + 替换为 -,将 / 替换为 _)
urlsafe = base64.urlsafe_b64encode(encoded_bytes)
print(urlsafe)  # b'SGVsbG8sIFdvcmxkIQ=='

# 解码 URL 安全
decoded = base64.urlsafe_b64decode(urlsafe).decode('utf-8')
print(decoded)  # Hello, World!

为 Data URL 编码

在 Python 中创建用于 Web 的 Data URL:

import base64
import mimetypes

def create_data_url(filepath):
    mime_type, _ = mimetypes.guess_type(filepath)
    with open(filepath, 'rb') as file:
        encoded = base64.b64encode(file.read()).decode('utf-8')
    return f"data:{mime_type};base64,{encoded}"

# 使用
data_url = create_data_url('logo.png')
print(data_url[:50])  # data:image/png;base64,iVBORw0KGgoAAAANSUhEU...

命令行中的 Base64

类 Unix 系统包含 base64 命令,用于直接在终端中快速进行编码和解码操作。

基本用法

# 编码字符串
echo "Hello, World!" | base64
# 输出: SGVsbG8sIFdvcmxkIQo=

# 解码字符串
echo "SGVsbG8sIFdvcmxkIQo=" | base64 -d
# 输出: Hello, World!

# 编码文件
base64 image.png > image.txt

# 解码文件
base64 -d image.txt > image-copy.png

# 不换行编码(对 Data URL 有用)
base64 -w 0 image.png > image-oneline.txt

macOS 差异

在 macOS 上,base64 命令的选项略有不同:

# 在 macOS 上解码
base64 -D image.txt > image-copy.png

# 在 macOS 上不换行编码
base64 -b 0 image.png > image-oneline.txt

实用命令行示例

# 从图像创建 Data URL
echo "data:image/png;base64,$(base64 -w 0 logo.png)"

# 编码剪贴板内容(Linux 使用 xclip)
xclip -o | base64

# 快速 API 身份验证标头
echo -n "username:password" | base64
# 输出: dXNlcm5hbWU6cGFzc3dvcmQ=

# 验证编码/解码后的文件完整性
md5sum original.pdf
base64 original.pdf | base64 -d | md5sum
# 两个校验和应该匹配

专业提示: 创建 Data URL 时使用 base64 -w 0(Linux)或 base64 -b 0(macOS)以避免会破坏 URL 格式的换行符。

Data URL 与内联图像

Data URL 使用 Base64 编码将文件内容直接嵌入 HTML、CSS 或 JavaScript 中。这消除了