DevToolbox
All articles

Base64编码详解:原理、使用场景与在线工具

· 6 min read

Base64 是开发者几乎每天都会接触的编码方式,却常常被误解为一种加密手段。本文将从原理出发,深入讲解 Base64 的工作机制、在前端开发中的实际应用,以及标准 Base64 与 URL 安全 Base64 的关键区别。

Base64 是什么

Base64 是一种将任意二进制数据转换为纯文本字符串的编码方案。它使用 64 个可打印的 ASCII 字符来表示数据,这 64 个字符包括:

  • 大写字母 A–Z(26 个)
  • 小写字母 a–z(26 个)
  • 数字 0–9(10 个)
  • 加号 + 和斜杠 /(2 个)
  • 等号 = 作为填充字符(padding)

编码原理:3 字节变 4 字符。Base64 每次取 3 个字节(24 位)的二进制数据,将其分割为 4 组,每组 6 位,再用查表的方式将每组 6 位映射为对应的 Base64 字符。

原始数据(3字节):  M        a        n
二进制表示:        01001101 01100001 01101110
重新分组(每6位):  010011  010110  000101  101110
十进制值:          19      22      5       46
Base64字符:        T       W       F       u
结果:              TWFu

当原始数据的字节数不是 3 的倍数时,使用 = 进行填充:剩余 1 字节时补两个 =,剩余 2 字节时补一个 =。这也解释了为什么 Base64 编码后的字符串长度总是 4 的倍数。

编码膨胀率:原始数据每 3 字节变为 4 个字符,因此 Base64 编码后的数据体积比原始数据大约 33%

为什么需要 Base64

Base64 存在的根本原因是:很多文本协议(如 HTTP 头、SMTP 邮件、HTML、XML)在设计时只考虑了 ASCII 可打印字符,无法安全传输任意二进制数据。

具体场景包括:

  • 电子邮件附件:SMTP 协议基于文本,邮件附件(图片、PDF 等)必须用 Base64 编码后才能嵌入邮件正文传输。
  • HTTP 基本认证Authorization: Basic dXNlcjpwYXNz 中,dXNlcjpwYXNz 就是 user:pass 的 Base64 编码。
  • 数据 URI:在 HTML/CSS 中直接嵌入二进制资源(图片、字体等)。
  • JWT(JSON Web Token):Header 和 Payload 部分使用 Base64url 编码(URL 安全变体)。
  • 密码学数据交换:公钥、证书、数字签名通常以 Base64 编码的 PEM 格式存储和传输。

图片转 Base64 的实际用途

将图片转换为 Base64 字符串,可以直接嵌入 HTML 或 CSS,无需额外的 HTTP 请求。

在 HTML 中内联图片:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" alt="1x1像素图片" />

在 CSS 中内联背景图:

.icon {
  background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==');
}

适合内联的场景:

  • 体积很小的图标(小于 2–4 KB)
  • 关键渲染路径上的图片(避免额外请求延迟)
  • 需要离线工作的 PWA 应用
  • HTML 邮件模板中的嵌入图片

不适合内联的场景:

  • 大图片(体积膨胀 33%,且无法利用浏览器缓存)
  • 多个页面复用的图片(内联后无法共享缓存)

标准 Base64 vs URL 安全 Base64

标准 Base64 中使用的 +/ 字符在 URL 中有特殊含义,会导致解析问题。因此 RFC 4648 定义了 URL 安全 Base64(Base64url),将两个特殊字符替换:

  • + 替换为 -(连字符)
  • / 替换为 _(下划线)
  • 末尾的填充 = 通常省略

对比示例:

// 原始字符串:"hello+world/test"
// 标准 Base64:
aGVsbG8rd29ybGQvdGVzdA==

// URL 安全 Base64:
aGVsbG8rd29ybGQvdGVzdA  (注意:无填充,且若含+/会被替换)

URL 安全 Base64 主要用于:JWT token、OAuth state 参数、URL 中传递的二进制数据(如图片预览链接中的内联数据)。

JavaScript 中的 btoa / atob 与注意事项

浏览器原生提供了 btoa()(编码)和 atob()(解码)两个函数:

// 编码
btoa('Hello, World!');  // "SGVsbG8sIFdvcmxkIQ=="

// 解码
atob('SGVsbG8sIFdvcmxkIQ==');  // "Hello, World!"

Unicode 陷阱:btoa() 只能处理 Latin-1 字符集,遇到中文或其他多字节 Unicode 字符会抛出 InvalidCharacterError

btoa('你好');  // 报错:InvalidCharacterError

正确处理 Unicode 的方法:先用 encodeURIComponent 将字符串转为 UTF-8 百分号编码,再编码:

// 编码含中文的字符串
function encodeBase64Unicode(str) {
  return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
    (match, p1) => String.fromCharCode(parseInt(p1, 16))
  ));
}

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

encodeBase64Unicode('你好世界');  // "5L2g5aW95LiW55WM"

在 Node.js 中,推荐使用 Buffer,它原生支持 UTF-8:

// Node.js 编码
Buffer.from('你好世界').toString('base64');  // "5L2g5aW95LiW55WM"

// Node.js 解码
Buffer.from('5L2g5aW95LiW55WM', 'base64').toString('utf8');  // "你好世界"

常见误区:Base64 不是加密

这是关于 Base64 最重要的一个认知:Base64 是编码,不是加密。

两者的本质区别在于:加密需要密钥,没有密钥就无法解密;而 Base64 解码不需要任何密钥,任何人拿到 Base64 字符串都能立即还原出原始数据。

// 任何人都能解码这段"看起来像乱码"的字符串
atob('5L2g5aW95LiW55WM');  // 立即得到 "你好世界"

常见的错误用法:

  • 将密码 Base64 编码后存入数据库(这与明文存储几乎没有区别)
  • 在 HTTP 请求中用 Base64 "隐藏"敏感参数
  • 认为 JWT 的 Payload 部分是加密的(实际上只是 Base64url 编码,完全可读)

如果需要保护数据机密性,请使用真正的加密算法,如 AES-GCM(对称加密)或 RSA/ECDH(非对称加密)。Base64 的唯一作用是解决二进制数据在文本环境中的传输问题。

小结

Base64 通过将每 3 字节二进制数据映射为 4 个可打印字符,解决了二进制数据在文本协议中传输的问题。前端开发中,它最常用于图片内联(小图标)和 JWT token 的 Payload 传递。处理中文等 Unicode 内容时要注意 btoa() 的限制,推荐使用封装好的工具函数或 Node.js 的 Buffer。最重要的是,始终记住 Base64 不提供任何安全保障——它只是换了一种形式表达数据,而不是保护数据。

Try it free
Base64 编码/解码工具
100% client-side · no signup · no upload
Open tool →