コンテンツにスキップ

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エンコードは不要(バイナリのまま送信)

この記事で使えるテストファイル

📚 リファレンス