大容量データアップロードする時に考えたいこと

2026-09-28に公開

Webアプリケーションで画像やファイルをアップロードする機能はよくあります。
通常の画像ファイルであれば、それほど複雑なことを考えなくても実装できます。

しかし、CADデータなど数GBを超えるような大容量ファイルを扱う場合、同じ設計のままで本当に問題ないのでしょうか?
今回は大容量データをアップロードの実装で得た学びをブログにしました。

一般的なファイルアップロード


画像などの比較的小さなファイルであれば、multipart/form-data を使ってバックエンドへ送信する方法が一般的です。

Browser
│
│ multipart/form-data
▼
Backend API
│
│ ファイルを保存
▼
Amazon S3

バックエンドでは、multipart/form-data として送信されたリクエストからファイルを取得し、S3などのオブジェクトストレージへ保存します。

比較的小さなファイルであれば、このような構成でも大きな問題にはなりません。

大容量ファイルのアップロード


大容量ファイルでは何が問題になるのか

では、例えば5GBのCADデータをアップロードするとします。

先ほどと同じ設計なら、

Browser
│
│ 5GB
▼
WAF / CDN / Load Balancer
│
│ 5GB
▼
Backend
│
│ 5GB
▼
S3

となります。

ユーザーからバックエンドを経由してS3へ、という経路を巨大なデータが通過します。

ここからいくつかの問題が発生します。

1. バックエンドのリソースを消費する


実装方法によっては、アップロードされたファイルを一度メモリ上に展開してからS3へ送信することがあります。

1ファイルが5GBなら、それだけで大きな負荷です。複数ユーザーが同時にアップロードすれば、影響はさらに大きくなります。

ストリーミング処理を利用すれば、ファイル全体をメモリへ載せる必要はありません。それでも、巨大な通信をアプリケーションサーバーが中継すること自体が、ネットワーク帯域、接続数、CPUなどのリソースを消費します。

2. タイムアウトやサイズ制限の影響を受ける


大容量ファイルはアップロード完了まで時間がかかります。

ブラウザとバックエンドの間には、CDN、WAF、Load Balancer など複数のサービスが挟まることがあります。それぞれについて、

* リクエストサイズ制限
* タイムアウト
* 接続維持時間

などを確認する必要があります。

バックエンドの実装だけが大容量ファイルに対応していればよい、というわけではありません。

3. バックエンドがファイルの中継地点になる


本来バックエンドが担当したいのは、

* 認証
* 認可
* DB更新
* ビジネスロジック

などです。

大容量ファイルをバックエンド経由でアップロードすると、巨大なデータをS3へ転送する役割まで担当することになります。

言ってしまえば、5GBのデータを右から左へ流しているだけの処理に、バックエンドのリソースを使うことになります。

ここで、実データはブラウザから直接S3へ送ればよいのでは、という考えが出てきます。

4. 経路上のサービスごとに料金がかかる


大容量ファイルでは、そのデータがどのサービスを通過するのかも見ます。

Browser
│
▼
CloudFront
│
▼
WAF
│
▼
ALB
│
▼
ECS / EC2
│
▼
NAT Gateway
│
▼
S3

CloudFront、WAF、ALB、NAT Gateway は、それぞれ別の料金がかかります。S3に保存する料金だけを見ればよいわけではありません。

付き方はサービスごとに違います。データ量で効きやすいのは NAT Gateway です。S3へ出す通信は Gateway 型の VPC Endpoint にすれば、NAT Gateway を経由せずに済みます。

どのようなアプローチがいいか?


Presigned URLで直接送る

巨大な実データをバックエンドへ送らない方法として、S3の Presigned URL があります。

① アップロード許可を要求

Browser
│
│ 「ファイルをアップロードしたい」
▼
Backend
│
│ 認証・認可
▼
Presigned URLを発行

② 実際のファイルをアップロード

Browser
│
│ ファイル本体
▼
S3

バックエンドが担当するのは、このユーザーがこのファイルをアップロードしてよいか、という制御です。許可できれば Presigned URL を発行します。

実データはブラウザからS3へ直接送ります。

制御の通信は Browser → Backend、データの通信は Browser → S3、と分けられます。大容量データをバックエンドやその手前のサービスに通す必要がなくなります。

ただし、S3へ1リクエストで送れるサイズには上限があります。単一PUTは5GBまでです。5GBを超えるファイルは、このままでは送れません。

Multipart Uploadに関して

そこで使うのが Multipart Upload です。ファイルをパートに分け、パートごとに Presigned URL を使って送ります。

10GB
↓ 分割
Part 1 ──→ S3
Part 2 ──→ S3
Part 3 ──→ S3
...

途中で失敗しても、失敗したパートだけ再送できます。パートを並列に送れば、速くなる場合もあります。

数GBのファイルなら、Presigned URL と Multipart Upload を組み合わせるのが現実的です。

⸻

バックエンドは完了を観測できない

直送にすると、別の問題が出ます。バックエンドは、アップロードが終わったことを自分では知りません。

Presigned URL を発行した時点で分かるのは、このユーザーがこのキーへアップロードしてよい、ということまでです。S3へ届いたか、途中で切れたかは、発行したリクエストの中では分かりません。

完了を知るには、別の経路が必要です。ブラウザから「アップロードし終わった」と通知してもらうか、S3のイベントで検知するか、です。

Multipart Upload では、パートを送っただけではオブジェクトは確定しません。すべてのパートが揃ったあと、完了要求が必要です。この完了をバックエンド経由にすれば、アップロード完了の把握にも使えます。

直送は、データを中継する役割をやめる代わりに、完了の観測を別の経路で取り戻す設計になります。

まとめ


小さなファイルなら、ブラウザからバックエンドを経由してS3へ保存する構成で十分な場合があります。

ファイルが大きくなると、その経路自体を疑います。バックエンドのリソース、途中のタイムアウトやサイズ制限、経路上のサービスごとの料金が、フォームアップロードのままでは効いてきます。S3へ1リクエストで送れるサイズにも、5GBという上限があります。

選択肢のひとつは、バックエンドが認証・認可と URL の発行を担当し、実データは Presigned URL でS3へ直接送ることです。5GBを超える場合は Multipart Upload と組み合わせます。

その代わり、バックエンドは完了を自分では観測できません。届いたかどうかは、クライアントの通知かS3のイベントで別途知る必要があります。

大容量ファイルを扱うときは、「アップロードできるか」だけではなく、そのデータを誰が受け取り、どのサービスを通り、どこまで再送でき、完了を誰が知るのかまで考えて設計します。