什么是Base64?图片怎么转换为Base64编码?

原创 发布日期:
17

你是否想过,为什么一张图片可以变成一串看起来毫无意义的乱码字符串,却还能在网页上正常显示?这背后的魔法,就是 Base64编码

从邮件附件到网页内嵌图片,从API数据传输到小程序图片处理,Base64几乎无处不在。它不是加密算法,却让二进制数据在文本世界里自由穿行。而图片转Base64,更是前端开发、数据传输中最常用的技能之一。

本文将从原理到实操,从代码到命令行,把Base64和图片转换这件事讲透。

一、什么是Base64?一句话讲清本质

Base64是一种基于64个可打印字符来表示任意二进制数据的编码方法。

它的核心目的只有一个:让二进制数据(图片、文件、视频)能在只支持文本的环境中安全传输。

比如早期的邮件系统只支持ASCII字符,你没法直接在邮件正文里塞一张图片。但如果把图片编码成一串由字母、数字和符号组成的文本,邮件系统就能正常处理了——这就是Base64诞生的原因。

Base64最早应用于邮件传输协议(MIME),在RFC 2045~RFC 2049中被完整定义和标准化。

二、Base64的字符集:64个字符,一个不多一个不少

Base64使用的字符集非常固定,一共64个可打印字符:

类别 字符范围 数量
大写字母 A~Z 26个
小写字母 a~z 26个
数字 0~9 10个
特殊符号 + 、/ 2个
合计64个

此外还有一个 "=" 符号,它不属于索引表,专门用于填充(Padding),确保编码结果的长度是4的倍数。

为什么是64个? 因为2的6次方等于64(2⁶=64),每6个比特(bit)可以表示64种状态,正好对应64个字符。这就是"Base64"名字的由来——64进制

什么是Base64?图片怎么转换为Base64编码?

三、Base64编码规则:3字节变4字符

这是整篇文章最核心的部分,理解了这个规则,你就理解了Base64的全部。

核心转换逻辑

步骤 说明
第1步 把原始二进制数据每3个字节(3×8=24位)分为一组
第2步 把这24位重新划分为4组,每组6位(4×6=24位)
第3步 每6位作为一个索引值,查Base64索引表,得到对应字符
第4步 如果原始数据不是3的倍数,用 "=" 补齐到4的倍数

举个例子:编码 "Man"

字符 ASCII码 二进制
M 77 01001101
a 97 01100001
n 110 01101110

三个字节共24位,划分为4个6位组:

6位组 二进制 十进制索引 Base64字符
第1组 010011 19 T
第2组 010110 22 W
第3组 000101 5 F
第4组 101110 46 u

所以 **"Man" → "TWFu"**,3个字符变成了4个字符。

填充规则(Padding)

当原始数据字节数不是3的倍数时:

原始字节数 ÷ 3 的余数 编码后字符数 补几个"="
余0(正好整除) 4的倍数 0个
余1 需补2个"=" "=="
余2 需补1个"=" "="

例如:"abcd"(4字节,余1)→ 编码为 **"YWJjZA=="**,末尾两个等号就是填充。

Base64编码后的数据长度比原始数据约多1/3(约33%),这是它最大的代价。

四、图片怎么转换为Base64编码?5种方法全覆盖

图片本质上就是二进制文件,转换为Base64的过程就是:读取图片的二进制数据 → 用Base64算法编码 → 输出字符串

以下5种方法覆盖了几乎所有使用场景。

方法1:Python(最推荐,最灵活)

Python内置了base64模块,3行代码即可完成

import base64

with open("photo.jpg", "rb") as f:
  encoded = base64.b64encode(f.read()).decode("utf-8")

print(encoded)

关键注意事项

要点 说明
必须用"rb"模式打开base64.b64encode()只接受bytes,用"r"模式会报TypeError
.decode("utf-8") 把编码结果从bytes转为字符串,方便在HTML中使用
大图要分块读 20MB以上的图片,一次性f.read()会占用双倍内存(原始+编码后),建议用base64.encodebytes()分块处理

如果需要带MIME前缀(用于HTML img标签)

import base64

with open("photo.jpg", "rb") as f:
  encoded = base64.b64encode(f.read()).decode("utf-8")

mime_type = "image/jpeg" # 或 image/png
result = f"data:{mime_type};base64,{encoded}"
print(result)

输出格式:data:image/jpeg;base64,/9j/4AAQSkZJRgABAQE...

方法2:JavaScript / 浏览器端(前端最常用)

在浏览器中,使用FileReader API可以将用户上传的图片直接转为Base64:

<input type="file" id="img_upload" accept="image/*">
<textarea id="base64_code" rows="10" cols="60"></textarea>

<script>
document.getElementById("img_upload").addEventListener("change", function() {
  var file = this.files[0];
  var reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = function() {
    document.getElementById("base64_code").value = this.result;
  };
});
</script>

核心逻辑reader.readAsDataURL(file)会自动完成"读取二进制→Base64编码→添加data:前缀"的全过程。

方法3:Go语言(后端/服务端场景)

Go标准库encoding/base64提供了简洁的实现:

package main

import (
  "encoding/base64"
  "fmt"
  "io/ioutil"
  "net/http"
)

func main() {
  bytes, _ := ioutil.ReadFile("./flower.jpg")
  mimeType := http.DetectContentType(bytes)

  var prefix string
  switch mimeType {
  case "image/jpeg": prefix = "data:image/jpeg;base64,"
  case "image/png": prefix = "data:image/png;base64,"
  }

  encoded := prefix + base64.StdEncoding.EncodeToString(bytes)
  fmt.Println(encoded)
}

Go的优势在于处理远程图片也非常方便,只需先http.Get()获取图片二进制数据,再进行编码即可。

方法4:命令行(最快,无需写代码)

如果你只是临时需要转换一张图片,命令行是最快的方式:

系统 命令
Linux / macOSbase64 -i image.png -o image_base64.txt
Windows PowerShell[Convert]::ToBase64String([IO.File]::ReadAllBytes("image.png"))

Linux的base64命令会直接把编码结果输出到文件或终端,零学习成本

方法5:在线转换工具(零代码,最省事)

不想写代码也不想开终端?直接用在线工具:

如福娃工具网的在线图片转Base64工具:https://www.fuwa.org/tools/imgtobase64.html

  • 上传图片 → 自动生成Base64字符串 → 复制使用

图片转Base64工具

五、Base64怎么转回图片?解码同样简单

编码是"图片→字符串",解码就是反过来:

语言 解码代码
Pythonbase64.b64decode(encoded_str),然后用open("out.jpg","wb").write(data)写入文件
JavaScriptatob(base64_str)得到二进制字符串,再转成Blob或Uint8Array
Gobase64.StdEncoding.DecodeString(encoded_str)

关键提醒: 如果Base64字符串缺少末尾的"="填充,解码前必须手动补全:

missing_padding = len(encoded_str) % 4
if missing_padding:
  encoded_str += "=" * (4 - missing_padding)

否则b64decode()会抛出binascii.Error: Incorrect padding错误。

六、Base64图片的优缺点:什么时候该用,什么时候不该用

维度 优点 缺点
体积 减少HTTP请求数量(一张图=一个请求) **体积增加约33%**,大图传输更慢
缓存 无需额外请求,首屏加载快无法被CDN缓存,每次访问都重新下载
兼容性 任何支持文本的地方都能用不支持懒加载,data URL立即解析
调试 图片和HTML在一起,方便管理 浏览器DevTools中看不到图片的尺寸、加载时间等信息

结论非常明确

  • 适合用Base64的场景:小图标(<10KB)、少量装饰图片、需要内嵌到JSON/CSS中的图片

  • 不适合的场景:大图(>50KB)、需要缓存的图片、大量图片的页面

一张20MB的PNG图片,经Base64编码后体积约26MB,且Python会同时在内存中保存原始bytes和编码后字符串——实际内存占用超过50MB。对服务端来说,这是实实在在的性能杀手。

七、实战对比:三种Python方式转换图片与Base64

方式 核心代码 适用场景 优缺点
直接读取文件open(path,"rb").read() 小图片,最简单 ✅ 最简洁 ❌ 大图内存爆炸
PIL/PillowImage.open()BytesIOb64encode 需要先处理图片(裁剪、压缩) ✅ 可预处理 ❌ 多一层依赖
OpenCVcv2.imencode()tobytes()b64encode 需要指定输出格式/质量 ✅ 可控质量 ❌ 依赖cv2库

代码示例(PIL方式)

from io import BytesIO
from PIL import Image
import base64

def image_to_base64(image_path):
  image = Image.open(image_path)
  buffer = BytesIO()
  image.save(buffer, format="JPEG")
  return base64.b64encode(buffer.getvalue()).decode("utf-8")

八、微信小程序中图片转Base64的三种方案

小程序开发中,图片转Base64是高频需求,主要有三种实现路径:

方案 核心API 优点 缺点
wx.getFileSystemManager().readFile()encoding: 'base64' 🚀 性能最优,代码最简 ⚠️ 仅支持本地文件
Canvas绘制转换canvas.toDataURL() ✅ 可裁剪/加水印/滤镜 ❌ 代码复杂,有绘制延迟
wx.request + ArrayBufferwx.arrayBufferToBase64() ✅ 支持网络图片 ❌ 受域名白名单限制

最推荐的方案是readFile,一行核心代码搞定:

wx.getFileSystemManager().readFile({
  filePath: tempFilePath,
  encoding: 'base64',
  success: (res) => {
    this.setData({ base64: `data:image/png;base64,${res.data}` });
  }
});

九、常见问题速答

Q:Base64是加密算法吗?

不是。 Base64只是一种编码方式,数据从一种形式转换为另一种形式,任何人都可以解码。它不能用于保护数据安全。

Q:为什么有些Base64字符串末尾没有"="?

因为有些场景(如URL传输)中"="会造成歧义,所以部分实现会自动去掉填充符。解码时需要手动补全。

Q:Base64和Base64URL有什么区别?

标准Base64使用"+/"两个字符,而Base64URL把"+/"替换成"-_",因为"+/"在URL中会被编码为"%XX"形式,造成额外麻烦。Python中可用base64.urlsafe_b64encode()实现。

Q:图片转Base64后,怎么在HTML中使用?

直接放在img标签的src属性中:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...">

写在最后

Base64不神秘,它就是一套把二进制翻译成文本的规则。3字节变4字符,64个可打印字符轮流出场,末尾不够就用"="补齐——就这么简单。

图片转Base64的核心也只有一句话:读取图片的二进制数据,然后用Base64算法编码。Python三行代码,JavaScript一个API,命令行一条指令,都能搞定。

但请记住它的代价:体积增加33%,无法缓存,不支持懒加载。小图用它锦上添花,大图用它雪上加霜。

选对工具,用对场景,Base64就是你手中最顺手的那把瑞士军刀。

打赏
THE END
作者头像
fuwa
我爱我的参差不齐 我即是自己的反义词