エラーの内容
S3にファイルをアップロードすると、次のエラーが返ってきます:
An error occurred (EntityTooLarge) when calling the PutObject operation:
Your proposed upload exceeds the maximum allowed object size.
アップロードは完全に停止します。ファイルはバケットに届きません。
原因
S3には常に混乱を引き起こす2つのサイズ制限があります:
- 単一PUTアップロード:リクエストあたり最大5 GB
- 最大オブジェクトサイズ:5 TB(マルチパートアップロードのみ)
標準のPutObject呼び出し(SDK、CLIのs3api put-object、または生のHTTP PUT)でこの制限に達すると、AWSは即座に拒否します。部分的なアップロードもリトライもありません。このエラーだけが返ってきます。
マルチパートアップロードが解決策です。ファイルを最低5 MBずつのチャンクに分割し(最後のパートはそれより小さくてもよい)、並列でプッシュし、S3がサーバー側で再組み立てします。50 GBのデータベースダンプでも、200 GBの動画アーカイブでも、この方法で問題なく動作します。
修正方法1:AWS CLI(クイックアップロードに推奨)
朗報です:aws s3 cpとaws s3 syncはすでにマルチパートを自動的に処理します。CLIでこのエラーが発生している場合は、おそらくs3api put-objectを使用しているためです。代わりに高レベルコマンドに切り替えてください。
# デフォルトで8 MBを超えるファイルには自動的にマルチパートを使用
aws s3 cp /path/to/largefile.tar.gz s3://your-bucket/largefile.tar.gz
チャンクサイズを調整したいですか?チャンクが大きいほどリクエスト数が少なくなり、高速接続に有効です:
aws s3 cp /path/to/largefile.tar.gz s3://your-bucket/largefile.tar.gz \
--multipart-threshold 64MB \
--multipart-chunksize 64MB
現在の設定を確認するには:
aws configure get s3.multipart_threshold
aws configure get s3.multipart_chunksize
またはAWS設定ファイルに永続的に設定するには:
[profile default]
s3 =
multipart_threshold = 64MB
multipart_chunksize = 64MB
max_concurrent_requests = 10
修正方法2:boto3 — プログラム的アップロードにTransferConfigを使用
コードでput_object()を使用していますか?それが原因です。upload_file()またはupload_fileobj()に置き換え、TransferConfigを付けてください:
import boto3
from boto3.s3.transfer import TransferConfig
s3 = boto3.client('s3')
config = TransferConfig(
multipart_threshold=1024 * 1024 * 64, # 64 MB
multipart_chunksize=1024 * 1024 * 64, # 64 MB チャンク
max_concurrency=10,
use_threads=True
)
s3.upload_file(
Filename='/path/to/largefile.tar.gz',
Bucket='your-bucket',
Key='largefile.tar.gz',
Config=config
)
print('アップロード完了')
ストリームやファイルオブジェクトからアップロードする場合は、代わりにupload_fileobj()を使用してください:
with open('/path/to/largefile.tar.gz', 'rb') as f:
s3.upload_fileobj(f, 'your-bucket', 'largefile.tar.gz', Config=config)
両方のメソッドは、ファイルがしきい値を超えると透過的にマルチパートを処理します。put_object()は常に単一PUTを実行するため、5 GBを超えるものは必ず失敗します。
修正方法3:boto3 APIによる手動マルチパートアップロード
完全な制御が必要ですか?カスタムリトライロジック、再開可能なアップロード、パートごとの進捗追跡が必要な場合は、このアプローチを使用します:
import boto3
import os
import math
s3 = boto3.client('s3')
BUCKET = 'your-bucket'
KEY = 'largefile.tar.gz'
FILE_PATH = '/path/to/largefile.tar.gz'
CHUNK_SIZE = 64 * 1024 * 1024 # 64 MB
# 1. 開始
mpu = s3.create_multipart_upload(Bucket=BUCKET, Key=KEY)
upload_id = mpu['UploadId']
parts = []
try:
file_size = os.path.getsize(FILE_PATH)
total_parts = math.ceil(file_size / CHUNK_SIZE)
with open(FILE_PATH, 'rb') as f:
for part_number in range(1, total_parts + 1):
data = f.read(CHUNK_SIZE)
response = s3.upload_part(
Bucket=BUCKET,
Key=KEY,
PartNumber=part_number,
UploadId=upload_id,
Body=data
)
parts.append({'PartNumber': part_number, 'ETag': response['ETag']})
print(f'パート {part_number}/{total_parts} をアップロード済み')
# 2. 完了
s3.complete_multipart_upload(
Bucket=BUCKET,
Key=KEY,
UploadId=upload_id,
MultipartUpload={'Parts': parts}
)
print('マルチパートアップロード完了')
except Exception as e:
# 3. 失敗時は必ずアボート — 不完全なアップロードもストレージ料金が発生する
s3.abort_multipart_upload(Bucket=BUCKET, Key=KEY, UploadId=upload_id)
raise e
修正を確認する
アップロードが完了したら、オブジェクトが実際に存在し、サイズが一致することを確認します:
# オブジェクトが存在することとサイズを確認
aws s3 ls s3://your-bucket/largefile.tar.gz
# ローカルファイルと比較
ls -lh /path/to/largefile.tar.gz
# オブジェクトのメタデータを確認
aws s3api head-object --bucket your-bucket --key largefile.tar.gz
マルチパートでアップロードされたオブジェクトには特徴的なETagがあります。これは-Nで終わり、Nはパート数です(例:12パートのアップロードの場合"abc123-12")。メタデータレスポンスにはx-amz-mp-parts-countも表示されます。
予防策
- 大きくなる可能性があるものには
put_object()を使わないようにしましょう。 デフォルトとしてTransferConfig付きのupload_file()を使用してください。小さいファイルも大きいファイルも適切に処理できます。 - 不完全なマルチパートアップロードを自動アボートするライフサイクルルールを設定しましょう。 失敗したアップロードはS3に孤立したパーツを残し、その分のストレージ料金が発生します。7日間のクリーンアップルールの設定は無料でできます:
aws s3api put-bucket-lifecycle-configuration \
--bucket your-bucket \
--lifecycle-configuration '{
"Rules": [{
"ID": "abort-incomplete-multipart",
"Status": "Enabled",
"Filter": {"Prefix": ""},
"AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 7}
}]
}'
- 既存の不完全なアップロードを定期的に確認しましょう:
aws s3api list-multipart-uploads --bucket your-bucket

