Base64 编码是软件开发中最广泛使用的数据编码方案之一。从在 HTML 和 CSS 中嵌入图片到通过 HTTP 和 SMTP 等文本协议传输二进制数据,Base64 无处不在。本指南从位级别解释其工作原理,涵盖所有主要用例,提供 JavaScript、Python 和命令行代码示例。
什么是 Base64 编码?
Base64 是一种二进制转文本的编码方案,使用 64 个可打印 ASCII 字符表示二进制数据。它设计用于通过仅支持文本的系统安全传输二进制数据。
"Base64" 名称来自使用 64 个字符的字母表:A-Z(26)、a-z(26)、0-9(10)、+(1)和 /(1)。= 用于填充。每 3 字节输入产生 4 个 Base64 字符,编码后数据约增大 33%。
Base64 不是加密。它不提供任何安全性。任何人都可以解码。其目的纯粹是编码:将二进制数据转换为文本安全格式。
The Base64 Alphabet (RFC 4648):
Index Char Index Char Index Char Index Char
─────────────────────────────────────────────────────────
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /
Padding character: =Base64 工作原理:逐步解析
Base64 编码将每组 3 个输入字节(24 位)转换为 4 个输出字符(每个 6 位):
- 取 3 字节输入数据(共 24 位)。
- 将 24 位分为四个 6 位组。
- 将每个 6 位值(0-63)映射到 Base64 字母表中的字符。
- 如果输入长度不是 3 的倍数,添加填充(
=)。
以编码字符串 "Hi!" 为例:
Encoding "Hi!" step by step:
Step 1: Convert ASCII to binary
'H' = 72 = 01001000
'i' = 105 = 01101001
'!' = 33 = 00100001
Step 2: Concatenate all bits
01001000 01101001 00100001 (24 bits total)
Step 3: Split into 6-bit groups
010010 | 000110 | 100100 | 100001
18 6 36 33
Step 4: Map to Base64 alphabet
18 → S
6 → G
36 → k
33 → h
Result: "Hi!" → "SGkh"
─────────────────────────────────────────
Encoding "Hi" (only 2 bytes - needs padding):
'H' = 01001000
'i' = 01101001
01001000 01101001 + 0000 (pad to 18 bits)
010010 | 000110 | 100100
18 6 36
18 → S, 6 → G, 36 → k, padding → =
Result: "Hi" → "SGk="Base64 的常见用例
Base64 编码出现在 Web 开发和软件工程的许多领域:
1. Data URI(在 HTML/CSS 中嵌入图片)
Data URI 允许直接在 HTML 或 CSS 中嵌入小文件,消除 HTTP 请求。适合小图标和 SVG:
<!-- Embedding a small PNG icon as a data URI -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB
CAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
alt="1x1 pixel" width="16" height="16" />
<!-- SVG data URI in CSS -->
<style>
.icon-arrow {
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz
0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2
h0PSIyNCI+PHBhdGggZD0iTTEyIDRsLTEuNDEgMS40MUwxNi4xNyAxMUg0dj
JoMTIuMTdsLTUuNTggNS41OUwxMiAyMGw4LTh6Ii8+PC9zdmc+');
width: 24px;
height: 24px;
}
</style>
<!-- Inline font as data URI (for critical fonts) -->
@font-face {
font-family: 'CriticalFont';
src: url('data:font/woff2;base64,d09GMgABAAAAA...') format('woff2');
font-display: swap;
}2. JWT 令牌
JWT 使用 Base64URL 编码(URL 安全变体)编码头部和载荷部分:
// JWT token structure: header.payload.signature
// Each part is Base64URL-encoded
const header = {
alg: "HS256",
typ: "JWT"
};
const payload = {
sub: "1234567890",
name: "Alice",
iat: 1516239022
};
// Base64URL encode (no padding, URL-safe chars)
function base64url(str) {
return btoa(str)
.replace(/\+/g, '-') // + → -
.replace(/\//g, '_') // / → _
.replace(/=+$/, ''); // remove padding
}
const encodedHeader = base64url(JSON.stringify(header));
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
const encodedPayload = base64url(JSON.stringify(payload));
// "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNTE2MjM5MDIyfQ"
// Final JWT: header.payload.signature
// eyJhbGci...IkpXVCJ9.eyJzdWIi...MjM5MDIyfQ.signature_here3. API 认证(HTTP Basic Auth)
HTTP 基本认证将用户名和密码编码为 Authorization 头中的 Base64 字符串:
// HTTP Basic Authentication
const username = 'admin';
const password = 'secret123';
// Encode credentials as Base64
const credentials = btoa(username + ':' + password);
// "YWRtaW46c2VjcmV0MTIz"
// Set the Authorization header
fetch('https://api.example.com/data', {
headers: {
'Authorization': 'Basic ' + credentials
// "Authorization: Basic YWRtaW46c2VjcmV0MTIz"
}
});
// Equivalent curl command:
// curl -H "Authorization: Basic YWRtaW46c2VjcmV0MTIz" https://api.example.com/data
// or simply:
// curl -u admin:secret123 https://api.example.com/data5. Kubernetes Secrets
Kubernetes 将秘密值存储为 YAML 清单中的 Base64 编码字符串:
# Kubernetes Secret manifest
apiVersion: v1
kind: Secret
metadata:
name: my-app-secrets
type: Opaque
data:
# Values must be Base64-encoded
# echo -n "mypassword" | base64 → bXlwYXNzd29yZA==
database-password: bXlwYXNzd29yZA==
# echo -n "sk-abc123xyz" | base64 → c2stYWJjMTIzeHl6
api-key: c2stYWJjMTIzeHl6
---
# Using stringData (Kubernetes encodes automatically)
apiVersion: v1
kind: Secret
metadata:
name: my-app-secrets-v2
type: Opaque
stringData:
# Plain text - Kubernetes handles Base64 encoding
database-password: mypassword
api-key: sk-abc123xyz6. 在 JSON 中存储二进制数据
JSON 原生不支持二进制数据。Base64 编码是在 JSON 载荷中包含二进制数据的标准方式:
{
"document": {
"name": "report.pdf",
"content_type": "application/pdf",
"data": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL..."
},
"avatar": {
"format": "png",
"width": 128,
"height": 128,
"data": "iVBORw0KGgoAAAANSUhEUgAAAIAAAACA..."
}
}JavaScript 中的 Base64
JavaScript 在浏览器和 Node.js 环境中提供内置的 Base64 编码和解码函数:
// ========== Browser: btoa() and atob() ==========
// Encode ASCII string to Base64
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
// Decode Base64 to ASCII string
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
console.log(decoded); // "Hello, World!"
// ========== Unicode strings (browser) ==========
// btoa() fails with non-ASCII characters
// btoa('Hello ') → Error!
// Solution: encode to UTF-8 first
function utf8ToBase64(str) {
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
(_, p1) => String.fromCharCode(parseInt(p1, 16))
)
);
}
function base64ToUtf8(b64) {
return decodeURIComponent(
atob(b64).split('').map(c =>
'%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join('')
);
}
// Modern approach (using TextEncoder/TextDecoder)
function encodeBase64(str) {
const bytes = new TextEncoder().encode(str);
const binString = Array.from(bytes, b => String.fromCodePoint(b)).join('');
return btoa(binString);
}
function decodeBase64(b64) {
const binString = atob(b64);
const bytes = Uint8Array.from(binString, c => c.codePointAt(0));
return new TextDecoder().decode(bytes);
}
// ========== Node.js: Buffer ==========
// Encode string to Base64
const base64 = Buffer.from('Hello, World!').toString('base64');
console.log(base64); // "SGVsbG8sIFdvcmxkIQ=="
// Decode Base64 to string
const text = Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString('utf-8');
console.log(text); // "Hello, World!"
// Encode binary data (file) to Base64
const fs = require('fs');
const imageBase64 = fs.readFileSync('image.png').toString('base64');
const dataUri = 'data:image/png;base64,' + imageBase64;
// URL-safe Base64 in Node.js
const urlSafe = Buffer.from('Hello!').toString('base64url');
console.log(urlSafe); // "SGVsbG8h" (no padding, URL-safe chars)注意:btoa() 和 atob() 在浏览器中只处理 ASCII 字符串。Unicode 文本需要先编码为 UTF-8。
Python 中的 Base64
Python 标准库的 base64 模块支持标准 Base64、URL 安全 Base64 和 Base32/Base16 编码:
import base64
# ========== Standard Base64 ==========
# Encode string to Base64
text = "Hello, World!"
encoded = base64.b64encode(text.encode('utf-8'))
print(encoded) # b'SGVsbG8sIFdvcmxkIQ=='
print(encoded.decode('ascii')) # "SGVsbG8sIFdvcmxkIQ=="
# Decode Base64 to string
decoded = base64.b64decode('SGVsbG8sIFdvcmxkIQ==')
print(decoded.decode('utf-8')) # "Hello, World!"
# ========== URL-Safe Base64 ==========
data = b'\xfb\xff\xfe' # bytes with +/- in standard Base64
standard = base64.b64encode(data) # b'+//+'
urlsafe = base64.urlsafe_b64encode(data) # b'-__-'
# Decode URL-safe Base64
decoded = base64.urlsafe_b64decode('-__-')
# ========== File encoding ==========
# Encode a file to Base64
with open('image.png', 'rb') as f:
file_base64 = base64.b64encode(f.read()).decode('ascii')
# Decode Base64 to a file
with open('output.png', 'wb') as f:
f.write(base64.b64decode(file_base64))
# ========== Working with JSON ==========
import json
payload = {
"name": "document.pdf",
"data": base64.b64encode(open('doc.pdf', 'rb').read()).decode('ascii')
}
json_str = json.dumps(payload)
# ========== Base32 and Base16 (Hex) ==========
base32 = base64.b32encode(b'Hello') # b'JBSWY3DP'
hex_encoded = base64.b16encode(b'Hello') # b'48656C6C6F'命令行 Base64
Linux/macOS 和 Windows 都提供内置的 Base64 编码解码工具:
# ========== Linux / macOS ==========
# Encode a string
echo -n "Hello, World!" | base64
# SGVsbG8sIFdvcmxkIQ==
# Decode a Base64 string
echo "SGVsbG8sIFdvcmxkIQ==" | base64 --decode
# Hello, World!
# Encode a file
base64 image.png > image.b64
# or
cat image.png | base64 > image.b64
# Decode a file
base64 --decode image.b64 > image_restored.png
# Pipe from curl - encode API response
curl -s https://api.example.com/data | base64
# One-liner: create a data URI from an image
echo "data:image/png;base64,$(base64 < icon.png)" > data-uri.txt
# ========== macOS-specific ==========
# macOS base64 uses -D instead of --decode
echo "SGVsbG8=" | base64 -D
# ========== OpenSSL (cross-platform) ==========
echo -n "Hello" | openssl base64
echo "SGVsbG8=" | openssl base64 -d
# ========== Windows PowerShell ==========
# Encode
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("Hello"))
# Decode
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("SGVsbG8="))URL 安全的 Base64 编码
标准 Base64 使用在 URL 中有特殊含义的 + 和 / 字符。URL 安全 Base64 替换了这些:
| 字符 | 标准 Base64 | URL 安全 Base64 |
|---|---|---|
| 第 62 个字符 | + | -(连字符) |
| 第 63 个字符 | / | _(下划线) |
| 填充 | = | 通常省略 |
URL 安全 Base64 用于 JWT 令牌、URL 参数、文件名安全编码等场景。
// URL-Safe Base64 encoding/decoding
// JavaScript (browser)
function toBase64Url(str) {
return btoa(str)
.replace(/\+/g, '-') // Replace + with -
.replace(/\//g, '_') // Replace / with _
.replace(/=+$/, ''); // Remove padding
}
function fromBase64Url(b64url) {
// Restore standard Base64
let b64 = b64url
.replace(/-/g, '+') // Restore +
.replace(/_/g, '/'); // Restore /
// Add padding if needed
while (b64.length % 4 !== 0) {
b64 += '=';
}
return atob(b64);
}
// Node.js (built-in support)
const encoded = Buffer.from('Hello!').toString('base64url');
// "SGVsbG8h"
const decoded = Buffer.from('SGVsbG8h', 'base64url').toString();
// "Hello!"
// Python
import base64
encoded = base64.urlsafe_b64encode(b'Hello!').rstrip(b'=')
# b'SGVsbG8h'
decoded = base64.urlsafe_b64decode(b'SGVsbG8h' + b'==')
# b'Hello!'性能考量
Base64 虽然无处不在,但有性能影响需要注意:
33% 大小开销:每 3 字节变为 4 字符。1MB 图片编码后约 1.37MB。
CPU 成本:编码解码需处理每个字节。批量操作考虑二进制传输。
不利于压缩:Base64 数据压缩效果差。应先压缩后编码。
Data URI 限制:大型 Base64 图片增加页面重量。仅对 5KB 以下图片使用。
大文件替代方案:超过 10KB 的文件使用 multipart form data 或二进制 WebSocket。
Base64 Size Overhead Examples:
Original Size Base64 Size Overhead
─────────────────────────────────────────
1 KB 1.37 KB +37%
10 KB 13.7 KB +37%
100 KB 137 KB +37%
1 MB 1.37 MB +37%
10 MB 13.7 MB +37%
Note: Actual overhead varies slightly due to
padding and line breaks (MIME uses 76-char lines).
Best practice thresholds:
< 5 KB → Data URI (inline) is fine
5-10 KB → Consider external file
> 10 KB → Always use external file/binary transfer何时不使用 Base64
Base64 并非总是正确选择。在以下场景中避免使用:
- 大文件传输:使用 multipart/form-data 或二进制协议
- 安全/加密:Base64 不是加密,使用 AES、RSA 等算法
- HTML 中的大图片:使用带缓存头的普通 img 标签
- 数据库存储:大多数数据库支持 BLOB 类型
- 带宽敏感:33% 开销在计量连接上会累积
常见问题
Base64 编码用于什么?
Base64 将二进制数据转换为文本以便安全传输。常见用途包括 Data URI、JWT 令牌、HTTP Basic 认证、邮件附件和 Kubernetes Secrets。
如何在 JavaScript 中 Base64 编码字符串?
浏览器中使用 btoa() 编码,atob() 解码。Unicode 需先 encodeURIComponent。Node.js 使用 Buffer.from(str).toString("base64")。
Base64 编码等同于加密吗?
不是。Base64 是编码方案,不是加密。任何人无需密钥即可解码。安全需求请使用 AES 或 RSA。
为什么 Base64 使数据增大 33%?
Base64 用 4 个字符表示 3 个字节。4/3 = 1.333,输出增大 33%。这是文本安全表示的代价。
Base64 和 Base64URL 有什么区别?
标准 Base64 用 + 和 /,在 URL 中有特殊含义。Base64URL 用 - 替换 + ,用 _ 替换 /,通常省略填充。JWT 和 URL 参数使用 Base64URL。
Base64 编码是每个开发者工具箱中的基础工具。它连接了二进制数据和文本系统,实现了 Data URI、JWT、API 认证等功能。理解位级工作原理、URL 安全变体和 33% 大小开销将帮助您有效使用 Base64。
Related Developer Tools and Guides
- Base64 Encoder / Decoder - Encode and decode Base64 strings online
- Image to Base64 Converter - Convert images to Base64 data URIs
- JWT Decoder - Decode and inspect JWT tokens
- Base64 Real-World Uses - 7 practical Base64 use cases
- Base64 Command Line Guide - Encode and decode Base64 in the terminal
- Base64 Image Embedding - Embed Base64 images in HTML and CSS
- JWT Token Explained - Understanding JSON Web Tokens
- API Authentication Guide - OAuth, JWT, and API key patterns