🖼️ 图片 ⇄ Base64 原理详解

编码原理 · 解码过程 · HTML 实战展示

Base64 Encoding Data URI 前端实战

1什么是 Base64?

计算机中所有数据都以二进制(0 和 1)存储。图片文件本质上是一长串字节(bytes),每个字节 8 位(bit)。

Base64 的核心思想:把任意二进制数据,用 64 个可打印的 ASCII 字符来表示。这样原本不可直接嵌入文本的二进制数据,就可以安全地在纯文本环境(HTML、CSS、JSON、XML、邮件等)中传输。

Base64 字符表(64 个字符)

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789 + /
6 位(bit)可以表示 2⁶ = 64 种不同值,恰好对应 64 个字符。这就是 Base64 名称的由来——以 64 为基数编码。

2编码过程(图片 → Base64 字符串)

核心步骤

① 读取图片原始字节
② 分组每 3 字节一组
3×8 = 24 bits
③ 切分每 6 bits 一段
24÷6 = 4 段
④ 查表映射到 64 字符
⑤ 补等号不足 3 字节用 =

图解:3 字节 → 4 个 Base64 字符

假设有 3 个字节的原始数据:01001101 01100001 01101110(即 ASCII "Man")

步骤操作结果
原始 3 字节 01001101 01100001 01101110 77 97 110(十进制)
连成 24 bits 010011010110000101101110
切成 4 个 6-bit 010011 / 010110 / 000101 / 101110 19 22 5 46
查 Base64 表 19→T, 22→W, 5→F, 46→u TWFu

补齐规则(Padding)

当原始字节数不是 3 的倍数时,需要用 = 补齐:

剩余字节数编码后字符数等号数量示例
1 字节4 个字符2 个 =TQ==
2 字节4 个字符1 个 =TWE=
3 字节4 个字符0 个TWFu

膨胀率

每 3 个原始字节 → 4 个 Base64 字符,所以编码后体积膨胀约 33%(4÷3 ≈ 1.33)。

例如:一张 150 KB 的 PNG 图片,Base64 编码后字符串大约 200 KB

这也是为什么网页中的小图标适合 Base64 内联(避免额外 HTTP 请求),但大图更适合用 URL 引用(避免 HTML 文件过大)。

3解码过程(Base64 字符串 → 图片)

解码是编码的逆过程

① 去 Padding去掉末尾 =
② 反向查表每个字符→6 bits 值
③ 拼接6 bits × 4 → 24 bits
④ 切 8-bit24 bits → 3 字节
⑤ 写入得到原始图片字节

JavaScript 解码示例

浏览器提供了两个内置 API 来完成编解码,无需手写算法:

// ========== 编码:图片文件 → Base64 字符串 ==========
const file = document.querySelector('input[type=file]').files[0];
const reader = new FileReader();
reader.onload = (e) => console.log(e.target.result);
reader.readAsDataURL(file);  // → data:image/png;base64,iVBORw0KG...

// ========== 解码:Base64 字符串 → 二进制数据 ==========
const base64 = "iVBORw0KGgo...";  // 去掉 "data:image/png;base64," 前缀
const raw = atob(base64);          // Base64 → 二进制字符串
const bytes = new Uint8Array(raw.length);
for (let i = 0; i < raw.length; i++) {
  bytes[i] = raw.charCodeAt(i);    // 得到每个字节的数值
}
// 用 bytes 创建 Blob:
const blob = new Blob([bytes], { type: 'image/png' });
API方向说明
btoa()字符串 → Base64Binary to ASCII
atob()Base64 → 字符串ASCII to Binary
FileReader.readAsDataURL()文件 → Data URL自动生成完整 data:... 前缀

4HTML 如何展示 Base64 图片

核心:Data URI Scheme

HTML 通过 Data URI(数据统一资源标识符) 直接内嵌 Base64 图片数据,无需额外的 HTTP 请求。

格式:

data:[<MIME 类型>][;base64],<Base64 数据>

示例:

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

三种使用方式

方式一:<img> 标签的 src 属性

<img
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..."
  alt="Base64 图片"
/>

方式二:CSS 的 background-image

.icon {
  width: 32px; height: 32px;
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0...");
}

方式三:<canvas> 动态绘制

const img = new Image();
img.onload = () => ctx.drawImage(img, 0, 0);
img.src = "data:image/png;base64,...";

各格式 MIME 对照

图片格式MIME 类型Data URI 前缀
PNGimage/pngdata:image/png;base64,
JPEGimage/jpegdata:image/jpeg;base64,
GIFimage/gifdata:image/gif;base64,
WebPimage/webpdata:image/webp;base64,
SVGimage/svg+xmldata:image/svg+xml;base64,
BMPimage/bmpdata:image/bmp;base64,
ICOimage/x-icondata:image/x-icon;base64,

静态演示

下面这张 1×1 像素的红色 PNG 图标完全内嵌在 HTML 中(Base64):

红色 PNG

↑ 放大到 200×200 的纯红色 PNG(原始 1×1 像素)

展开查看 Base64 源码
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4
AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEA
mpwYAAAA/klEQVR4nO2UMQ7CMAxFXcROD8DAxMjcBT
FxG5ZOwsjC0pEzcAFYGNkYGFCYqhoJqWqwFYfuUf6T
rL8cxxIkgkwZAL4ARC+XGzq/A+AOwAOAEYALAGYA4
lC0ZwBSEXyk0PcehH7JOFr33kEpZbmjKYq3nnkfWO
ckENoEYAvUI5JzgCxwGqF7JfAtVixbsY0pYxPboEl
C0hP4X0SF9kVXQBRW1xui1cBdENfCK8B8FFoo0REQ
dbndLnCWAwwACNQ3gsgFaDWBOKctP/GL4AtAfV7PD
hC1/3OPWAbfKfw4gf1JpB79zFe4v1IsLsDXo5Z4AI
f2VH43yGLcAC8AriTcNXWxL1FGH3FV88D9AAAAAEl
FTkSuQmCC

5动手试试:上传图片实时转换

📁

点击或拖拽图片到这里

支持 PNG / JPG / GIF / WebP / SVG 等格式

6优缺点总结

✅ 优点❌ 缺点
减少 HTTP 请求数(小图标场景) 体积膨胀约 33%
无需额外文件管理,一切内嵌 HTML / CSS 文件变大,影响首屏加载
适合邮件、JSON 等纯文本场景 浏览器无法单独缓存 Base64 图片
跨域无限制(不需要 CORS) 修改图片需要重新编码,维护困难
最佳实践:小图标(< 2KB)用 Base64 内联;大图用 URL 引用配合 CDN。