AWS S3・CloudFrontのファイルアップロード上限まとめ|マルチパート・署名付きURL
AWS を使ったファイルアップロード機能を構築する際、S3・CloudFront・API Gateway・Lambda それぞれに異なるサイズ制限があり、どの層がボトルネックになるかを把握しておくことは非常に重要です。本記事では、各サービスの上限値を整理し、大容量ファイルを扱うためのマルチパートアップロードと署名付き URL の使い方、PHP での実装例まで解説します。
Amazon S3 のアップロード上限
S3 へのオブジェクトアップロードには、方式によって上限サイズが異なります。
| アップロード方式 | 最大サイズ | 備考 |
|---|---|---|
| PUT Object(単体) | 5 GB | 1リクエストでアップロードできる上限 |
| Multipart Upload | 5 TB | 1オブジェクトの最大サイズ |
| 1パートあたり | 最小 5 MB〜最大 5 GB | 最後のパートのみ 5 MB 未満可 |
| パート数 | 最大 10,000 パート | マルチパート時の上限 |
AWS は 100 MB 以上のファイルにはマルチパートアップロードを推奨しており、ネットワーク障害時の再送効率や並列転送によるスループット向上の観点からも、大容量ファイルには積極的に使うべきです。
マルチパートアップロードが必要なケース
マルチパートアップロードは、1つのオブジェクトを複数のパートに分割してそれぞれを独立したリクエストで送信し、最後に結合する方式です。以下のようなケースで有効です。
- 100 MB 以上のファイル:AWS が推奨するマルチパート切替ラインです。
- ネットワーク不安定な環境:途中でエラーが発生しても失敗したパートだけ再送できます。
- スループット最大化:複数パートを並列でアップロードすることで転送速度を向上できます。
- アップロード一時停止・再開:Upload ID を保存しておけばセッションをまたいで再開できます。
マルチパートアップロードの流れは大きく3ステップです。
- 開始(CreateMultipartUpload): Upload ID を取得する
- パート送信(UploadPart): 各パートをアップロードし、ETag を記録する
- 完了(CompleteMultipartUpload): パート番号と ETag の一覧を送信してオブジェクトを確定する
途中でキャンセルする場合は AbortMultipartUpload を呼ばないと、未完了のパートがストレージ料金として課金され続けます。S3 バケットのライフサイクルポリシーで「未完了のマルチパートアップロードを N 日後に削除」を設定しておくことを強く推奨します。
Presigned URL の有効期限とサイズ
署名付き URL(Presigned URL)を使うと、S3 へのアクセス権限を持たないクライアント(ブラウザ・モバイルアプリなど)から直接 S3 へファイルをアップロードできます。サーバーを中継しないため、大容量ファイルでも効率的です。
| 項目 | 制限・仕様 |
|---|---|
| 最大有効期限(IAMユーザー発行) | 7 日間(604,800 秒) |
| 最大有効期限(IAMロール発行) | ロールのセッション時間内(最大12時間) |
| アップロード可能なファイルサイズ | 単体 PUT の場合は最大 5 GB |
| マルチパートへの対応 | 各パートに個別の Presigned URL を発行 |
Presigned URL はバックエンドで生成してクライアントに返し、クライアントはその URL に対して直接 PUT リクエストを送ります。URL には署名が含まれているため、期限内に正しいファイルをアップロードする場合のみ成功します。
CloudFront の body size 制限
CloudFront を経由してオリジン(S3 や EC2 など)にリクエストを転送する場合、リクエストボディのサイズに制限があります。
| 設定 | デフォルト値 | 最大値 |
|---|---|---|
| リクエストボディサイズ(デフォルト) | 1 MB | ディストリビューション設定で変更可 |
| Lambda@Edge 経由の場合 | 1 MB | 1 MB(変更不可) |
| CloudFront Functions の場合 | — | リクエストボディへのアクセス不可 |
CloudFront ディストリビューションの設定で「Allow requests with body」を有効にし、上限を引き上げることができますが、Lambda@Edge では 1 MB の上限が変更できないことに注意してください。大容量ファイルのアップロードには CloudFront を経由させず、Presigned URL でクライアントから S3 に直接アップロードするアーキテクチャを採用することを推奨します。
API Gateway の Payload 制限
API Gateway(REST API / HTTP API いずれも)にはペイロードサイズの上限があります。
| API タイプ | 最大ペイロードサイズ | 備考 |
|---|---|---|
| REST API | 10 MB | バイナリサポートを有効にした場合も同様 |
| HTTP API | 10 MB | — |
| WebSocket API | 128 KB(メッセージ)/ 32 KB(フレーム) | — |
API Gateway の 10 MB 制限は AWS のサービスクォータに分類されており、緩和申請はできません。10 MB を超えるファイルを API Gateway 経由でアップロードするのは設計上の誤りと考え、Presigned URL パターンへの移行を検討してください。
Lambda 経由のファイル制限
Lambda 関数でファイルを受け取る場合、API Gateway から渡されるイベントペイロードに上限があります。また Lambda 自体にも以下の制限があります。
| 制限項目 | 値 |
|---|---|
| 同期呼び出し(Request)ペイロード | 6 MB |
| 同期呼び出し(Response)ペイロード | 6 MB |
| 非同期呼び出しペイロード | 256 KB |
| /tmp ディレクトリの容量 | デフォルト 512 MB(最大 10 GB) |
| 最大実行時間 | 15 分 |
Lambda でファイルを処理する場合、一時ファイルは /tmp に書き込みます。デフォルトは 512 MB ですが、Lambda 設定でエフェメラルストレージを最大 10 GB まで拡張できます(追加料金あり)。
PHP での S3 マルチパートアップロードコード例
AWS SDK for PHP(v3)を使ったマルチパートアップロードの実装例です。SDK の MultipartUploader クラスを使うと、チャンク分割・再試行・完了処理を自動で処理してくれます。
use Aws\S3\S3Client;
use Aws\S3\MultipartUploader;
use Aws\Exception\MultipartUploadException;
$s3 = new S3Client([
'region' => 'ap-northeast-1',
'version' => 'latest',
]);
$uploader = new MultipartUploader($s3, '/path/to/large-file.mp4', [
'bucket' => 'your-bucket-name',
'key' => 'uploads/' . basename('/path/to/large-file.mp4'),
'before_initiate' => function (\Aws\Command $command) {
// アップロード開始前のフック
},
'before_upload' => function (\Aws\Command $command) {
// 各パートアップロード前のフック(プログレス表示など)
},
'concurrency' => 5, // 並列アップロード数
'part_size' => 10 * 1024 * 1024, // 1パート = 10 MiB
]);
try {
$result = $uploader->upload();
echo 'アップロード完了: ' . $result['ObjectURL'];
} catch (MultipartUploadException $e) {
// 失敗したパートから再開する例
$uploader = new MultipartUploader($s3, '/path/to/large-file.mp4', [
'state' => $e->getState(),
]);
$result = $uploader->upload();
}
Presigned URL を発行して、クライアントから直接 S3 にアップロードさせる方法はこちらです。
use Aws\S3\S3Client;
$s3 = new S3Client([
'region' => 'ap-northeast-1',
'version' => 'latest',
]);
// 署名付きURLを生成(有効期限: 15分)
$cmd = $s3->getCommand('PutObject', [
'Bucket' => 'your-bucket-name',
'Key' => 'uploads/' . uniqid('', true) . '.jpg',
'ContentType' => 'image/jpeg',
]);
$request = $s3->createPresignedRequest($cmd, '+15 minutes');
$presignedUrl = (string) $request->getUri();
// このURLをクライアントに返す
// クライアントはこのURLに PUT リクエストでファイルを直接送信する
echo json_encode(['upload_url' => $presignedUrl]);
アーキテクチャ選択のガイドライン
- 〜10 MB:API Gateway → Lambda → S3 でシンプルに実装可能
- 10 MB〜100 MB:Presigned URL でクライアントから S3 に直接アップロードを推奨
- 100 MB〜5 GB:Presigned URL + マルチパートアップロードで安定した転送を実現
- 5 GB 超:マルチパートアップロード必須(PUT 単体では不可)
DevLab のしきい値ファイルを使ったテスト手順
実際に S3 のアップロード設定を検証するには、正確なサイズのテストファイルが必要です。DevLab の境界値テスト用ファイルを使うと、特定のサイズ前後の動作を効率よく確認できます。
- DevLab の 境界値テスト用ファイル一覧 からテストしたいサイズのファイルをダウンロードします。
- マルチパート切替ラインを検証する場合は PNG テスト画像 の大サイズ版も活用できます。
- ダウンロードしたファイルを
aws s3 cpコマンドまたは SDK のPutObject/MultipartUploaderでアップロードし、上限前後のファイルでの成功・失敗を確認します。
この記事で使えるテストファイル
- 境界値テスト用ファイル一覧 — S3・API Gateway・Lambda 各上限の検証に
- 10MB 境界値テストセット — API Gateway 10 MB 上限の直前・直後を確認
- 25MB 境界値テストセット — マルチパート推奨ライン前後の動作確認に
- PNG テスト画像一覧 — 画像アップロードパイプラインの動作確認に