Unicode/UTF-8テキストのBase64エンコード

Base64エンコード時にUnicodeやUTF-8文字を正しく扱う方法を解説。UTF-8変換の手順、btoa()のブラウザ固有の問題、クロスプラットフォームの解決策を紹介します。

Encoding

詳細な説明

Base64は文字ではなくバイトに対して動作します。ASCII範囲外の文字(アクセント付き文字、CJK文字、絵文字、数学記号)をテキストに含む場合、Base64エンコードの前にまず文字エンコーディング(ほぼ必ずUTF-8)を使ってテキストをバイト列に変換する必要があります。

btoa() の問題:

ブラウザの btoa() 関数は文字列を受け取りますが、各文字を1バイト(Latin-1エンコーディング)として扱います。コードポイントが255を超える文字は InvalidCharacterError を発生させます:

btoa("Hello");     // Works: "SGVsbG8="
btoa("café");    // Error! ́ is above Latin-1
btoa("😀");      // Error! Emoji code point is way above 255

解決策:まずUTF-8にエンコードする

TextEncoderを使用したモダンなアプローチ:

function encodeUnicode(str) {
  const utf8Bytes = new TextEncoder().encode(str);
  const binaryString = Array.from(utf8Bytes, b => String.fromCharCode(b)).join("");
  return btoa(binaryString);
}

function decodeUnicode(base64) {
  const binaryString = atob(base64);
  const bytes = Uint8Array.from(binaryString, c => c.charCodeAt(0));
  return new TextDecoder().decode(bytes);
}

encodeUnicode("Hello 😀"); // "SGVsbG8g8J+YgA=="
decodeUnicode("SGVsbG8g8J+YgA=="); // "Hello 😀"

レガシーアプローチ(現在も広く使用):

function utoa(str) {
  return btoa(unescape(encodeURIComponent(str)));
}
function atou(b64) {
  return decodeURIComponent(escape(atob(b64)));
}

この方法は、encodeURIComponent() が文字列をUTF-8パーセントエンコードされたバイトに変換し、unescape() がそれらのパーセントシーケンスを btoa() が処理できるシングルバイト文字に戻すために機能します。

Pythonでは自然に動作:

import base64
text = "Hello 😀"
encoded = base64.b64encode(text.encode("utf-8")).decode("ascii")
decoded = base64.b64decode(encoded).decode("utf-8")

Pythonは文字列からバイト列への変換(.encode("utf-8"))とBase64処理(b64encode())を自然に分離しており、プロセスが明示的でエラーが起きにくくなっています。

クロスプラットフォームの相互運用性: 重要なルールは、エンコーダーとデコーダーの両方がBase64前に使用する文字エンコーディングについて合意する必要があることです。クライアントでUTF-8でエンコードし、サーバーでLatin-1と仮定してデコードすると、マルチバイト文字が破損します。UTF-8がユニバーサルなデフォルトです。特別な理由がない限り常にUTF-8を使用してください。

よくある間違い: Base64がUnicodeをネイティブに扱えると思い込むこと。Base64は文字エンコーディングについて何も知りません。生のバイトを処理するだけです。文字エンコーディングのステップはエンコード前とデコード後に行う必要があります。

ユースケース

国際的な文字(中国語、アラビア語、絵文字)を含むユーザー送信フォームデータをBase64エンコードして、URLクエリパラメータに含める場合に使用します。

試してみる — Base64 Encoder

フルツールを開く