Toolypet
返回博客
Dev

Base64编码的一切 - 从原理到实战应用

全面了解Base64编码:什么是Base64、为什么需要它、如何使用它,配合实战示例。从内嵌图片到JWT。

Toolypet Team

Toolypet Team

Development Team

6 分钟阅读

Base64编码的一切

"这个图片怎么通过API发送?" "这个二进制数据怎么放入JSON?"

答案是Base64

本指南将完整介绍从Base64原理到实战应用的所有内容。


什么是Base64?

Base64是一种将二进制数据转换为文本的编码方式。

为什么需要?

问题Base64解决方案
邮件无法发送二进制转换为文本发送
JSON无法包含二进制转换为字符串包含
URL不允许特殊字符仅使用URL安全字符
HTML内嵌图片转换为Data URL

特点

  • 使用64个字符:A-Z, a-z, 0-9, +, /(标准)
  • 大小增加:比原始数据大约33%
  • 可逆:编码 ↔ 解码完全还原
  • 不是加密:任何人都能解码

Base64原理

编码过程

原始字符串: "Man"

1. ASCII转换
   M = 77 = 01001101
   a = 97 = 01100001
   n = 110 = 01101110

2. 按6位分割
   010011 | 010110 | 000101 | 101110
      19  |   22   |    5   |   46

3. 转换为Base64字符 (A=0, B=1, ... Z=25, a=26, ...)
   19 = T
   22 = W
   5  = F
   46 = u

结果: "TWFu"

Base64字符表

索引: 字符
0-25:   A-Z
26-51:  a-z
52-61:  0-9
62:     +
63:     /
填充:   =

填充 (=)

如果原始长度不能被3整除,添加填充

"M"   → "TQ=="  (2个填充)
"Ma"  → "TWE="  (1个填充)
"Man" → "TWFu"  (无填充)

语言实现

JavaScript(浏览器)

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

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

// Unicode处理(中文等)
function encodeUnicode(str) {
  return btoa(encodeURIComponent(str).replace(
    /%([0-9A-F]{2})/g,
    (_, p1) => String.fromCharCode(parseInt(p1, 16))
  ));
}

function decodeUnicode(str) {
  return decodeURIComponent(
    Array.from(atob(str), c =>
      '%' + c.charCodeAt(0).toString(16).padStart(2, '0')
    ).join('')
  );
}

// Unicode测试
const chinese = '你好世界';
const encodedChinese = encodeUnicode(chinese);
console.log(encodedChinese);
console.log(decodeUnicode(encodedChinese)); // "你好世界"

Node.js

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

const decoded = Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString('utf-8');
console.log(decoded); // "Hello, World!"

// 文件编码
const fs = require('fs');

const imageBuffer = fs.readFileSync('image.png');
const base64Image = imageBuffer.toString('base64');
console.log(base64Image.substring(0, 50) + '...');

Python

import base64

# 编码
encoded = base64.b64encode(b'Hello, World!').decode('utf-8')
print(encoded)  # "SGVsbG8sIFdvcmxkIQ=="

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

# Unicode(中文)
chinese = '你好世界'
encoded_chinese = base64.b64encode(chinese.encode('utf-8')).decode('utf-8')
print(encoded_chinese)

# 文件编码
with open('image.png', 'rb') as f:
    base64_image = base64.b64encode(f.read()).decode('utf-8')

Go

package main

import (
    "encoding/base64"
    "fmt"
)

func main() {
    // 编码
    data := "Hello, World!"
    encoded := base64.StdEncoding.EncodeToString([]byte(data))
    fmt.Println(encoded) // "SGVsbG8sIFdvcmxkIQ=="

    // 解码
    decoded, _ := base64.StdEncoding.DecodeString(encoded)
    fmt.Println(string(decoded)) // "Hello, World!"

    // URL安全Base64
    urlSafe := base64.URLEncoding.EncodeToString([]byte(data))
    fmt.Println(urlSafe)
}

实战应用

1. 内嵌图片(Data URL)

<!-- 直接在HTML中嵌入图片 -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" alt="1x1 red pixel">
// 文件 → Base64 Data URL
function fileToDataUrl(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// 使用
const file = document.getElementById('fileInput').files[0];
const dataUrl = await fileToDataUrl(file);
document.getElementById('preview').src = dataUrl;

2. 通过API发送图片

// 客户端
async function uploadImage(file) {
  const base64 = await fileToBase64(file);

  const response = await fetch('/api/upload', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      filename: file.name,
      contentType: file.type,
      data: base64,
    }),
  });

  return response.json();
}

function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      // 移除 data:image/png;base64, 前缀
      const base64 = reader.result.split(',')[1];
      resolve(base64);
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}
// 服务器 (Node.js)
app.post('/api/upload', (req, res) => {
  const { filename, contentType, data } = req.body;

  // Base64 → Buffer → 保存文件
  const buffer = Buffer.from(data, 'base64');
  fs.writeFileSync(`uploads/${filename}`, buffer);

  res.json({ success: true, filename });
});

3. JWT令牌

// JWT = Header.Payload.Signature (各Base64URL编码)

const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';

// 解码Payload
const payload = token.split('.')[1];
const decoded = JSON.parse(atob(payload));
console.log(decoded);
// { sub: "1234567890", name: "John Doe", iat: 1516239022 }

4. Basic认证

// HTTP Basic Authentication
const username = 'user';
const password = 'password';

const credentials = btoa(`${username}:${password}`);

fetch('/api/protected', {
  headers: {
    'Authorization': `Basic ${credentials}`,
  },
});

// 请求头: Authorization: Basic dXNlcjpwYXNzd29yZA==

5. 邮件附件(MIME)

Content-Type: application/pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="document.pdf"

JVBERi0xLjQKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMiAwIFIK
Pj4KZW5kb2JqCjIgMCBvYmoKPDwKL1R5cGUgL1BhZ2VzCi9LaWRzIFszIDAgUl0K
...

Base64变体

URL安全Base64

标准URL安全
+-
/_
=可省略
// URL安全编码
function toUrlSafeBase64(str) {
  return btoa(str)
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');
}

// URL安全解码
function fromUrlSafeBase64(str) {
  // 还原填充
  const pad = str.length % 4;
  const padded = pad ? str + '='.repeat(4 - pad) : str;

  return atob(
    padded
      .replace(/-/g, '+')
      .replace(/_/g, '/')
  );
}

Base64 vs Base32 vs Base16

编码字符数大小增加使用场景
Base6464+33%通用
Base3232+60%不区分大小写时
Base16 (Hex)16+100%哈希、颜色代码

注意事项

1. 不是加密

// 不要用于安全目的
const password = btoa('mySecretPassword');
// 任何人都能用atob()还原!

// 如果需要加密,先加密再Base64
const encrypted = await encryptAES(data, key);
const encoded = btoa(encrypted);

2. 大小增加

// 原始: 1MB图片
// Base64: ~1.33MB (增加33%)

// 大文件直接上传更高效
// 使用FormData + multipart/form-data

3. Unicode处理

// 浏览器btoa()只支持Latin-1
btoa('中文'); // Error: The string contains characters outside of the Latin1 range

// 需要Unicode处理
function encodeUnicode(str) {
  return btoa(unescape(encodeURIComponent(str)));
}

4. 换行

// 某些系统每76个字符添加换行
// MIME标准: 76字符换行

// 删除换行
const cleaned = base64String.replace(/[\r\n]/g, '');

性能优化

流式编码

// 分块处理大文件
async function* encodeFileInChunks(file, chunkSize = 1024 * 1024) {
  const reader = file.stream().getReader();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    // 按块Base64编码
    yield Buffer.from(value).toString('base64');
  }
}

使用Web Worker

// worker.js
self.onmessage = function(e) {
  const { action, data } = e.data;

  if (action === 'encode') {
    const result = btoa(data);
    self.postMessage({ result });
  }
};

// main.js
const worker = new Worker('worker.js');
worker.postMessage({ action: 'encode', data: largeString });
worker.onmessage = (e) => console.log(e.data.result);

调试工具

Base64 Encoder/Decoder

  1. 输入文本或文件
  2. 点击编码/解码按钮
  3. 复制结果

CLI

# 编码
echo -n "Hello, World!" | base64
# SGVsbG8sIFdvcmxkIQ==

# 解码
echo "SGVsbG8sIFdvcmxkIQ==" | base64 -d
# Hello, World!

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

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

常见问题

Q1: Base64为什么增加33%?

A:因为3字节(24位)用4个字符(4×6=24位)表示。

  • 3字节 → 4字符
  • 增加率:(4-3)/3 = 33%

Q2: 为什么需要填充(=)?

A:解码器需要它来知道原始长度。填充数量表示最后一组的字节数。

Q3: 什么时候使用Base64URL?

A:在URL或文件名中使用时。标准Base64的+/在URL中有特殊含义,所以替换为-_

Q4: 内嵌图片的优缺点?

A

  • 优点:减少HTTP请求、简化缓存
  • 缺点:HTML大小增加、无法单独缓存图片
  • 建议:仅用于小图标(2KB以下)

Q5: 如何验证是否为有效Base64?

A:用正则检查格式,然后尝试解码:

function isBase64(str) {
  const regex = /^[A-Za-z0-9+/]*={0,2}$/;
  if (!regex.test(str)) return false;

  try {
    atob(str);
    return true;
  } catch {
    return false;
  }
}

总结

Base64要点:

  1. 用途:二进制 → 文本转换
  2. 大小:比原始数据大33%
  3. 安全:不是加密(任何人都能解码)
  4. 变体:URL安全使用-_
  5. 应用:Data URL、JWT、Basic Auth、MIME

相关工具

工具用途
Base64 Encoder/DecoderBase64编码/解码
JWT DecoderJWT令牌分析
JSON FormatterJSON格式化
Base64编码开发数据APIJavaScript

关于作者

Toolypet Team

Toolypet Team

Development Team

The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.

Web DevelopmentCSS ToolsDeveloper ToolsSEOSecurity