1.はじめに
こんにちは!株式会社iimonでフロントエンドエンジニアをしている川口と申します!
自分が所属しているチームでは、不動産仲介会社向けの拡張機能を開発しているのですが、開発中に画像を扱うことが多々あり、Base64に触れる機会が多いです。これまでなんとなくの認識でBase64に触れていましたが、今回改めてBase64とはどんなものなのか調べたため、以下にまとめていきたいと思います。
2. Base64とは
そもそもBase64って何
base64とは、バイナリーからテキストへの符号化を行う手法のグループデータであり、バイナリーデータを64を基数とする表現に変換することで、ASCII文字列で表現するもの。
Base64が定められていた経緯
base64というデータ変換方法が定められたのは、メールを送信するためのSMTPで画像や音声データを送信するためです。かつてSMTPはASCIIという7bitで表現される英数字しか送信することができず、画像や音声データを扱うことはできませんでした。そのため、バイナリデータをASCII文字へ変換するBase64が定められました。
3. Base64を使用するメリット・デメリット
Base64を利用するメリット
webブラウザからサーバーへのデータ送信
Fetch APIなどを使って、Webブラウザからサーバーにデータを送信する際、BlobデータをBase64形式に変換することでテキスト形式で扱えるため、HTTPリクエストの本文などに埋め込んで送信することが可能になります。
データの埋め込み
HTMLなどの文書形式に画像を埋め込むことができます。例えばHTML内に直接画像を埋め込むことで、外部ファイルの参照を減らし、単一のファイルでコンテンツを管理できます。
プリロードの利便性
ページを読み込む際に、Base64エンコードされた画像は外部ファイルとして別途読み込む必要がなく、HTMLとして埋め込まれるため、ページのパフォーマンスを向上させることができます。
データURI
Base64化された画像は、DataURIとして扱うことができます。これは、画像データを含んだURLを作成するため、動的に画像を生成したり、プレビューを表示したりする際に便利です。
Base64を利用するデメリット
ファイルサイズの膨張
Base64エンコードされたデータは、元のバイナリデータよりも約1.37倍大きくなります。これにより通信量やストレージ容量を増やすことになります。
処理的負荷
Base64エンコードやデコードは当然ですが処理負荷がかかります。大量の画像データをBase64に変換する場合、処理速度に影響を与える可能性があります。
キャッシュ効率の低下
Base64エンコードされたデータは、外部ファイルとしてキャッシュされることが難しいため、再利用性が低下します。また、画像をBase64エンコードすると、画像をキャッシュすることができないため、再読み込みの必要性が生じる場合があります。
4. Base64エンコード
base64のアルゴリズムはRFC 4648に記載されています。
超〜ざっくりと説明するとファイルのバイナリデータを6bitずつ取り出し、ASCII文字へ変換し4文字ずつにします。
実際にエンコードしてみる
今回は理解のために手動でBase64エンコードをしてみたいと思います。
今回は文字列’iimon!’をbase64に変換してみたいと思います。
1. 文字列を2進数に変換する
16進数 i ⇒ 69 i ⇒ 69 m ⇒ 6d o ⇒ 6f n ⇒ 6e ! ⇒ 21 2進数 i ⇒ 0110 1001 i ⇒ 0110 1001 m ⇒ 0110 1101 o ⇒ 0110 1111 n ⇒ 0110 1110 ! ⇒ 0010 0001
2.バイナリを6bitづつに分割し余った部分に0を追加する
iimon ⇒ 011010010110100101101101011011110110111000100001 6bitに分割 011010, 010110, 100101, 101101, 011011, 110110, 111000, 100001
3. base64変換表よりASCII文字列に変換する
val | ASCII | val | ASCII | val | ASCII | val | ASCII |
---|---|---|---|---|---|---|---|
0 | A | 17 | R | 34 | i | 51 | z |
1 | B | 18 | S | 35 | j | 52 | 0 |
2 | C | 19 | T | 36 | k | 53 | 1 |
3 | D | 20 | U | 37 | l | 54 | 2 |
4 | E | 21 | V | 38 | m | 55 | 3 |
5 | F | 22 | W | 39 | n | 56 | 4 |
6 | G | 23 | X | 40 | o | 57 | 5 |
7 | H | 24 | Y | 41 | p | 58 | 6 |
8 | I | 25 | Z | 42 | q | 59 | 7 |
9 | J | 26 | a | 43 | r | 60 | 8 |
10 | K | 27 | b | 44 | s | 61 | 9 |
11 | L | 28 | c | 45 | t | 62 | + |
12 | M | 29 | d | 46 | u | 63 | / |
13 | N | 30 | e | 47 | v | pad | = |
14 | O | 31 | f | 48 | w | ||
15 | P | 32 | g | 49 | x | ||
16 | Q | 33 | h | 50 | y |
011010 ⇒ a 010110 ⇒ W 100101 ⇒ l 101101 ⇒ t 011011 ⇒ b 110110 ⇒ 2 111000 ⇒ 4 100001 ⇒ h
4. 4文字ずつに区切り、足りない分は=を追加する
"aWlt b24h"
確認してみましょう
今回は手動で文字列をBase64に変換してみましたが、JavaScriptでは
- バイナリデータをASCIIに変換するbtoaメソッド
- ASCIIをバイナリに変換するatobメソッド
が存在します。
実際に先ほどの手動変換が正しかったか確認してみましょう!
正しく変換できていますね!
5. おわりに
今回Base64について調べ、また実際に手動でエンコードすることにより、Base64エンコードでどのような処理が行われているのか、なんのためにエンコードする必要があるのかに関しての理解を深めることができました。今後も業務内でBase64に触れることがあると思いますが、今回調べた内容を思い出しながら実装ができればと思います。
参考:
https://developer.mozilla.org/ja/docs/Glossary/Base64
https://datatracker.ietf.org/doc/html/rfc4648#section-4
https://developer.mozilla.org/ja/docs/Web/API/btoa