画像アップロードの最適化パイプライン

アップロードするだけでリサイズ・軽量化・位置情報の除去まで済む画像管理の作り方

画像最適化WebPEXIF除去オブジェクトストレージアップロード
読了時間: 8分

はじめに

宿のサイトは写真が命です。ところがスマホやカメラで撮った写真をそのまま載せると、1枚5MBといった巨大なファイルがサイトに並ぶことになります。ページの表示は遅くなり、モバイル通信のお客様にも負担がかかります。

かといって、記事を書くたびに画像編集ソフトでリサイズするのは現実的ではありません。この記事では、アップロードするだけで最適化が完了する仕組みの作り方を紹介します。

アップロードされたファイルを検査する

拡張子は信用しない

まず前提として、アップロードされたファイルは信用できません。ファイル名の末尾が「.jpg」でも、中身が画像とは限らないからです。

ファイル受け入れの検査
サイズ確認

上限を超えるファイル、空のファイルを拒否

形式の申告を確認

許可した画像形式(JPEG・PNG・WebP・GIF・AVIF)以外を拒否

中身を実際に読む

画像処理ライブラリで解析し、申告どおりの画像か確認

不一致なら拒否

「JPEGと名乗っているのに中身が違う」ファイルをここで止める

3番目の「中身を実際に読む」が重要です。ファイルの先頭には形式ごとに決まった印(シグネチャ)があり、これを画像処理ライブラリで確認します。名前と中身が食い違うファイルは、この時点で弾かれます。

なお、ベクター形式の画像(SVG)は許可していません。SVGはその中にスクリプトを書けてしまうため、画像のふりをした攻撃の経路になり得るからです。

ファイル名を使わない

保存するときのファイル名には、アップロードされた元の名前を使いません。ランダムな識別子で新しい名前を付けます。

元の名前をそのまま使うと、同名ファイルで既存の画像を上書きされたり、名前に細工をして意図しない場所へ保存されたりする可能性があります。元のファイル名は、管理画面での表示用にデータベースへ記録するだけです。

自動で最適化する

リサイズと形式変換

検査を通った画像は、そのまま保存せず加工します。

元が小さい画像を無理に拡大しないよう、「収まる場合はそのまま」という設定にしています。拡大するとぼやけるだけで、良いことがありません。

位置情報を落とす

スマホで撮った写真には、撮影場所の緯度経度が埋め込まれていることがあります。宿の外観写真をそのまま公開すると、画像ファイルから正確な住所が読み取れてしまう恐れがあります。

今回使った画像処理ライブラリは、変換時に付加情報を引き継がない仕様のため、WebPへ変換する過程で位置情報は自動的に削除されます。撮影時の向き情報だけは、削除する前に画像自体の回転として適用しておきます。

アニメーションは壊さない

GIF形式の画像は、動くもの(アニメーション)である可能性があります。これを静止画に変換すると動きが失われるため、GIFだけは最適化処理をスキップして元のまま保存する例外を設けました。

自動化するときは、こうした「例外にすべきケース」を見落とさないことが大切です。

保存先の使い分け

公開用と非公開用を分ける

画像はオブジェクトストレージ(ファイル専用の保管サービス)に保存しますが、保管場所は用途で分けています。

ファイル保管の使い分け
公開ストレージ

ブログ・お知らせの画像。URLを知っていれば誰でも閲覧可能

非公開ストレージ

家電の取扱説明書PDFなど。認証を通した配信のみ許可

宿泊者向けの資料は、URLが漏れただけで誰でも見られる状態にはしたくありません。非公開ストレージに置き、専用の配信経路を通じて、権限のある人にだけ渡すようにしました。

さらに、保存した直後に「本当に意図した保管場所に入ったか」を確認しています。設定ミスで非公開ファイルが公開ストレージに入ってしまう事故を防ぐためです。想定と違えば、すぐ削除してエラーにします。

使用中の画像は削除させない

記事で使っている画像を削除してしまうと、公開中のページに画像が表示されなくなります。そこで削除前に、その画像がどこかの記事で使われていないかを確認し、使用中なら削除を拒否するようにしました。

表示のときも最適化する

保存時の最適化に加えて、表示するときにも「見る人の画面サイズに合わせた大きさ」で配信する仕組みを使っています。スマホには小さい画像、大きなディスプレイには大きい画像が自動的に届きます。

また、画像の説明文(代替テキスト)は4言語分を管理画面で設定できるようにしました。目の見えない方が読み上げ機能で閲覧する際や、画像が読み込めなかった際に表示される文章です。

まとめ

画像パイプラインで押さえたのは、次の3点です。

  1. 中身を検査する — 拡張子や申告された形式を信用せず、実際に読んで確認する
  2. アップロードするだけで完結 — リサイズ・形式変換・位置情報の除去を自動化
  3. 保管場所を用途で分ける — 公開して良いものと、認証が要るものを物理的に分離