Base64エンコードでファイルサイズが33%増える理由
「Base64でエンコードするとファイルサイズが約33%増える」と聞いたことはありませんか? これはなぜなのでしょうか。この記事では、Base64エンコードの仕組みと、ファイルサイズが増加する数学的な理由、そして開発現場での影響を解説します。
Base64とは何か
Base64は、バイナリデータをASCII文字のみで表現するエンコード方式です。メールの添付ファイル(MIME)、データURIスキーム、JWTトークン、Basic認証ヘッダーなど、テキストしか扱えないプロトコルでバイナリデータを送受信するために使われます。
使用する文字は A–Z(26文字)、a–z(26文字)、0–9(10文字)、+、/ の合計64文字(=Base64)と、パディング用の = です。
なぜ33%増えるのか
Base64は 3バイトのバイナリを4文字のASCIIに変換 します。
- 3バイト = 24ビット
- 24ビット ÷ 6ビット = 4つのBase64文字(各文字は6ビットを表す)
つまり、元データの 3バイト → 4文字 になります。サイズ比は 4 ÷ 3 ≈ 1.333... なので、約33.3%増加 します。
元バイナリ: | 0x4D | 0x61 | 0x6E | ← 3バイト
01001101 01100001 01101110
↓ 6ビットずつに分割
010011 010110 000101 101110
↓ Base64文字に変換
T W F u ← 4文字(= 4バイト)
具体的なサイズ増加の計算
| 元のファイルサイズ | Base64後のサイズ | 増加量 |
|---|---|---|
| 1 MB(1,000,000 B) | 約 1.333 MB | +333 KB |
| 10 MB | 約 13.33 MB | +3.33 MB |
| 25 MB(Gmail上限) | 約 33.3 MB | +8.33 MB |
| 100 MB | 約 133.3 MB | +33.3 MB |
正確な計算式は以下の通りです。
import math
def base64_size(original_bytes: int) -> int:
"""Base64エンコード後のバイト数を計算"""
# 3バイトを4文字に変換、4の倍数にパディング
return math.ceil(original_bytes / 3) * 4
original = 10_000_000 # 10 MB
encoded = base64_size(original)
print(f"元: {original:,} B")
print(f"後: {encoded:,} B")
print(f"増加率: {encoded/original*100:.1f}%")
# → 元: 10,000,000 B
# → 後: 13,333,336 B
# → 増加率: 133.3%
改行文字によるさらなる増加
MIME規格(メール)では、Base64のデータを76文字ごとに \r\n(CRLF)で改行することが求められます。この改行も追加のバイトとなるため、サイズが若干さらに増加します。
def base64_mime_size(original_bytes: int, line_length: int = 76) -> int:
"""MIME形式(76文字改行)のBase64サイズを計算"""
b64_chars = math.ceil(original_bytes / 3) * 4
line_count = math.ceil(b64_chars / line_length)
return b64_chars + line_count * 2 # CRLF = 2バイト/行
開発への影響
APIでのファイル送信
REST APIでファイルをJSONボディに含めて送る場合、Base64エンコードが必要になります。
// ファイルをBase64に変換してJSONで送る
const file = document.getElementById('file').files[0];
const reader = new FileReader();
reader.onload = (e) => {
const base64 = e.target.result; // "data:image/png;base64,iVBORw0KGgo..."
fetch('/api/upload', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ file: base64, name: file.name })
});
};
このとき、APIのリクエストサイズ上限はBase64後のサイズで判断されます。10MBのファイルを送る場合、JSONボディは約13.3MB以上になることに注意してください。
メール添付(SMTP)
SMTPプロトコルはASCIIテキストベースのため、添付ファイルはBase64でエンコードされます。Gmailの添付上限は25MBですが、これはエンコード前のファイルサイズが対象です(内部でのエンコードはGmailが処理)。ただし、SMTP経由で直接送信する場合はエンコード後のサイズが制限の対象となるため注意が必要です。
img タグのdata URI
<!-- Base64埋め込み画像 -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." />
HTMLに画像をインライン埋め込みする場合も、画像のBase64サイズ分だけHTMLファイルが大きくなります。大きな画像のインライン埋め込みはページ読み込み速度に影響するため避けるのが一般的です。
Base64をデコードして元のサイズに戻す
まとめ
- Base64は 3バイト → 4文字 に変換するため、サイズが 約33.3%増加 する
- MIME改行(76文字ごと)があるとさらにわずかに増加する
- JSONボディでファイルを送るAPIでは、Base64後のサイズでリクエスト上限が決まる
- HTMLフォームの
multipart/form-dataではBase64エンコードは不要(バイナリのまま送信)