跳到内容

AWS S3·CloudFront 文件上传限制汇总|分块上传·预签名 URL

分类:云·AWS
本文目前仅提供日文版本。我们正在进行翻译工作。

使用 AWS 构建文件上传功能时,S3、CloudFront、API Gateway 和 Lambda 各自都有不同的大小限制。理解哪一层可能成为瓶颈非常重要。本文整理了各服务的限制值,解释了用于处理大文件的分块上传和预签名 URL 的使用方法,以及 PHP 实现示例。

S3 上传方式与大小 PUT (single) ≤ 5 GB Multipart upload 5 MB ~ 5 TB / object Object size limit (S3) 5 TB max 注意:CloudFront / API Gateway / Lambda 有各自的请求体限制
图:S3 上传大小层级(单次 PUT 5GB / 分段 5TB)

Amazon S3 上传限制

上传对象到 S3 的大小限制因方法而异。

上传方式 最大大小 备注
PUT Object(单个) 5 GB 每个请求的上传限制
Multipart Upload 5 TB 单个对象的最大大小
每个部分 最小 5 MB ~ 最大 5 GB 仅最后一个部分可以小于 5 MB
部分数量 最多 10,000 个部分 分段上传时的上限

AWS 建议对 100 MB 以上的文件使用分块上传。从网络故障时的重传效率和并行传输提升吞吐量的角度来看,应该积极地用于大文件。

需要分段上传的情况

分段上传是一种方法,将一个对象分成多个部分,分别以独立的请求发送,最后进行合并。在以下情况下很有效。

  • <strong>100 MB 或更大的文件</strong>:这是 AWS 推荐的分段上传阈值。
  • <strong>网络不稳定的环境</strong>:即使在传输中途出错,也只需重新发送失败的分块。
  • <strong>最大化吞吐量</strong>:并行上传多个分块可提高传输速度。
  • <strong>上传暂停·恢复</strong>:保存 Upload ID 可以跨会话恢复。

分段上传流程大致分为3个步骤。

  1. <strong>启动</strong>(CreateMultipartUpload):获取上传 ID
  2. <strong>发送分块</strong>(UploadPart):上传每个分块并记录 ETag
  3. <strong>完成</strong>(CompleteMultipartUpload):发送部分号和 ETag 列表以确定对象

如果取消上传而不调用 <code>AbortMultipartUpload</code>,未完成的分段将继续作为存储费用被收费。强烈建议在S3存储桶的生命周期策略中设置"删除N天后未完成的多部分上传"。

预签名 URL 的有效期和大小

使用带签名的 URL (Presigned URL),没有 S3 访问权限的客户端(如浏览器或移动应用)可以直接将文件上传到 S3。由于服务器不充当中介,大文件也可以高效处理。

项目 限制与规格
最大有效期(IAM 用户颁发) 7天(604,800秒)
最大有效期(IAM 角色颁发) 在角色的会话时间内(最长12小时)
最大可上传文件大小 单一PUT最多5GB
多部分支持 为每个部分发行单独的 Presigned URL

预签名 URL 在后端生成并返回给客户端,客户端然后向该 URL 直接发送 PUT 请求。由于 URL 包含签名,它仅在有效期内上载正确文件时成功。

CloudFront的body大小限制

当通过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 的有效负载限制

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 服务配额,无法增加。通过 API Gateway 上传超过 10 MB 的文件被认为是设计缺陷;请考虑迁移到预签名 URL 模式。

通过 Lambda 的文件限制

在 Lambda 函数中接收文件时,API Gateway 传递的事件有效负载有大小限制。此外,Lambda 本身还具有以下约束。

限制项目
同步调用(Request)有效负载 6 MB
同步调用(Response)有效负载 6 MB
异步调用有效负载 256 KB
<code>/tmp</code> 目录的存储容量 默认 512 MB(最大 10 GB)
最大执行时间 15分钟

在 Lambda 中处理文件时,临时文件会写入 <code>/tmp</code>。默认值为 512 MB,但可以通过 Lambda 配置将临时存储扩展至最大 10 GB(需要额外费用)。

PHP中S3多部分上传代码示例

这是使用 AWS SDK for PHP(v3)实现分块上传的示例。使用 SDK 的 <code>MultipartUploader</code> 类可以自动处理分块、重试和完成处理。

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();
}

以下是如何发行预签名 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]);

架构选择指南

  • <strong>~10 MB</strong>:可通过 API Gateway → Lambda → S3 简单实现
  • <strong>10 MB–100 MB</strong>:建议使用预签署 URL 直接从客户端上传到 S3
  • <strong>100 MB~5 GB</strong>:使用 Presigned URL + 分块上传实现稳定传输
  • <strong>超过 5 GB</strong>:必须使用分块上传(单独 PUT 不可行)

使用 DevLab 阈值文件的测试步骤

要实际验证 <code>S3</code> 上传设置,您需要精确大小的测试文件。使用 DevLab 的边界值测试文件,您可以高效地验证特定大小前后的行为。

  1. 从 DevLab 的 <a href="/ja/files/threshold/">边界值测试文件列表</a> 中下载所需大小的文件。
  2. 验证分段切换阈值时,也可以利用 <a href="/ja/files/images/png/">PNG 测试图像</a>的大尺寸版本。
  3. 使用 <code>aws s3 cp</code> 命令或 SDK 的 <code>PutObject</code> / <code>MultipartUploader</code> 上传下载的文件,并验证大小限制前后文件的成功或失败情况。

本文中可用的测试文件

  • <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">边界值测试文件列表</a> — 用于验证 S3、API Gateway、Lambda 各上限
  • <a href="/ja/files/threshold/10mb/" class="text-primary-600 dark:text-primary-400 hover:underline">10MB 边界值测试集合</a> — 确认 API Gateway 10MB 上限的直前·直后
  • <a href="/ja/files/threshold/25mb/" class="text-primary-600 dark:text-primary-400 hover:underline">25MB 边界值测试集</a> — 用于验证多部分推荐线前后的行为
  • <a href="/ja/files/images/png/" class="text-primary-600 dark:text-primary-400 hover:underline">PNG 测试图像列表</a> — 用于验证图像上传管道功能

相关文章

  • <a href="/ja/blog/how-to-test-upload-limit/" class="text-primary-600 dark:text-primary-400 hover:underline">如何正确测试文件上传大小限制</a>
  • <a href="/ja/blog/php-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">PHP 文件上传实现方法|验证·存储·安全完全指南</a>
  • <a href="/ja/blog/multipart-form-data-overhead/" class="text-primary-600 dark:text-primary-400 hover:underline">准确计算 multipart/form-data 开销</a>
  • <a href="/ja/blog/mb-vs-mib-file-size/" class="text-primary-600 dark:text-primary-400 hover:underline">MB和MiB不一样!文件大小单位的陷阱</a>

常见问题

单个 S3 PUT 请求上传的最大文件大小是多少?

单一PUT操作最多支持5GB。对于更大的文件,可使用分块上传,支持最多5TB。

S3 预签名 URL 的过期时间是多少?

默认值为 15 分钟,最多可设置为 7 天(604800 秒)。这是使用 IAM 用户凭证生成时的上限。

通过 CloudFront 时上传大小限制会如何变化?

CloudFront的默认请求body大小限制是GET为0,POST/PUT最大20MB。建议采用将大型文件直接上传到S3的设计。