はじめに
エンジニア未経験で入社し、初めてAWSに触れる中で、画像をAmazon S3にアップロードする方法が複数あることを知りました。
その中でも、署名付きPUT URLと署名付きPOSTという2つの方法があり、何を基準に使い分ければ良いのか迷ったため、今回はAWS公式ドキュメントをもとに、それぞれの違いやメリット・デメリットを整理してみました。
1. S3への直接アップロードの仕組み
S3への画像アップロードには、バックエンドを経由して画像を保存する方法と、ブラウザからS3へ直接アップロードする方法があります。
今回取り上げる署名付きPUT URLと署名付きPOSTは、どちらも後者の方法です。
この構成では、バックエンドはアップロード用の署名情報を発行し、画像本体はブラウザからS3へ直接送信します。そのため、バックエンドで画像を受け取ってS3へ転送する処理が不要になります。
また、ブラウザにAWSのシークレットアクセスキーを渡す必要もありません。ただし、署名発行APIでは、誰にどのオブジェクトへのアップロードを許可するかを適切に判断する必要があります。
AWS公式:署名付きURLを使用したオブジェクトのアップロード
2. 署名付きPUT URLと署名付きPOSTの仕組み
PUT:署名付きURLにファイルを送信する
署名付きPUT URLでは、バックエンドが発行したURLに対してHTTPのPUTリクエストを送り、ファイルをリクエストボディに指定します。
フォームフィールドを組み立てる必要がなく、ブラウザ側の実装が比較的シンプルです。Content-Typeなどを署名対象ヘッダーに含めた場合は、署名時と異なる値で送信すると署名の検証に失敗します。
ファイルサイズについては、署名付きPOSTとは異なり、POSTポリシーによる範囲指定はできません。
POST:フォームとポリシーを使って送信する
署名付きPOSTでは、バックエンドから送信先URLとフォームフィールドを受け取り、multipart/form-data形式でファイルをアップロードします。
PUTとの大きな違いは、POSTポリシーでアップロード条件を指定できることです。
例えば、次のような条件を設定できます。
- アップロードするコンテンツのサイズ範囲
-
Content-Typeの値やプレフィックス - 保存先のオブジェクトキーや、そのプレフィックス
サイズ範囲を指定するcontent-length-rangeは、次のように記述します。
["content-length-range", 1, 10485760]
この例では、アップロードするコンテンツのサイズを1バイトから10MiB(10 × 1,024 × 1,024バイト)までに指定しています。(範囲外のアップロードはS3側で拒否されます)
一方で、PUTと比べると、フォームフィールドやポリシーなど、扱う項目は多くなります。
3. PUTとPOSTを比較する
それぞれの違いを表にまとめると、次のようになります。
| 比較項目 | 署名付きPUT URL | 署名付きPOST |
|---|---|---|
| 送信形式 | ファイルをリクエストボディに指定 | multipart/form-data |
| バックエンドから受け取るもの | 署名付きURL | URLとフォームフィールド |
| ブラウザ側の実装 | 比較的シンプル |
FormDataの組み立てが必要 |
| サイズ範囲の指定 | POSTポリシーによる範囲指定は不可 |
content-length-rangeで指定可能 |
Content-Typeの制約 |
署名対象に含めることで値を固定できる | ポリシーで完全一致・プレフィックスを指定可能 |
| 向いているケース | シンプルなアップロード | サイズ範囲などをS3側で検証したい場合 |
4. 最大10MiBの画像をアップロードするなら?
例えば、次のような要件のWebアプリを想定します。
- ユーザーが画像をアップロードできる
- ファイルサイズは最大10MiB
- 画像本体はブラウザからS3へ直接送信する
PUTでも画像のアップロードは可能ですが、ブラウザ側でファイルサイズを確認するだけでは、リクエストを改変された場合まで防げません。
S3側でもサイズ範囲を検証し、条件に合わないアップロードを拒否したい場合は、署名付きPOSTが候補にあがります。
5. PUT・POST共通の注意点
署名の有効期限と保存先の管理
署名付きURLは、URLを知っている人が有効期限内に利用できます。署名付きPOSTも、発行したURLやフォームフィールドを第三者に利用されないように扱う必要があります。
そのため、署名発行APIでは認証・認可を行い、有効期限を必要以上に長く設定しないよう気をつけましょう。
また、署名付きPUT URLは1回限りの使い捨てではありません。有効期限内に繰り返し利用でき、同じキーのオブジェクトが存在すると上書きされる可能性があります。
意図しない上書きを避けるため、PUT・POSTのどちらでも保存先のキーを適切に管理することが重要です。
CORSの設定
ブラウザのJavaScriptから別オリジンのS3へアップロードする場合は、S3バケットでCORSを設定する必要があります。
許可するオリジン、HTTPメソッド(PUTやPOST)、リクエストヘッダーなどを設定しますが、これはブラウザのクロスオリジンアクセスを制御するためのもので、S3へのアクセス権限とは別の仕組みです。
まとめ
今回は、S3への直接アップロードにおける署名付きPUT URLと署名付きPOSTの違いを整理しました。
- PUT: ファイルをそのまま送信でき、ブラウザ側の実装が比較的シンプル
- POST: POSTポリシーを使い、サイズ範囲などの条件をS3側で検証できる
今回調べてみて、単にアップロードできるかどうかだけでなく、どの条件を、どの段階でチェックするかが使い分けのポイントの一つだと理解できました!