Laravel 操作S3时10GB大文件move/copy功能失效问题
Laravel S3存储大文件move/copy操作失败的解决方法
问题原因
AWS S3对单步copyObject操作的文件大小限制为5GB,而Laravel的Storage facade默认的move/copy方法仅调用了常规的S3复制接口,没有处理超过5GB的大文件分块复制场景,因此10GB的文件操作会直接失败,且可能仅返回false而不抛出异常。
解决方案
直接使用AWS SDK的MultipartCopy类实现分块复制,再结合删除源文件完成move操作。以下是修改后的代码:
try { // 获取S3客户端实例 $s3Client = Storage::disk('s3')->getClient(); $bucket = config('filesystems.disks.s3.bucket'); $sourceKey = $param['source']; $targetKey = $param['target']; // 获取源文件的大小信息 $sourceMeta = $s3Client->headObject([ 'Bucket' => $bucket, 'Key' => $sourceKey, ]); $fileSize = $sourceMeta['ContentLength']; // 初始化分块复制,设置每块大小为100MB(可根据服务器内存调整) $multipartCopy = new \Aws\S3\MultipartCopy($s3Client, [ 'Bucket' => $bucket, 'Key' => $targetKey, 'CopySource' => "{$bucket}/{$sourceKey}", ], [ 'part_size' => 100 * 1024 * 1024, ]); // 执行分块复制 $copyResult = $multipartCopy->copy(); // 复制成功后删除源文件(move操作的核心逻辑) if ($copyResult['@metadata']['statusCode'] === 200) { $s3Client->deleteObject([ 'Bucket' => $bucket, 'Key' => $sourceKey, ]); dd(true); } else { dd(false); } } catch (\Exception $e) { return [ "status" => 0, "msg" => $e->getMessage(), ]; }
额外注意事项
- 权限检查:确保你的IAM用户拥有
s3:PutObject、s3:GetObject、s3:DeleteObject以及s3:ListBucket权限,分块操作需要这些权限支持。 - 超时设置:大文件复制耗时较长,需在
config/filesystems.php的S3配置中增加超时参数:
's3' => [ // 原有配置... 'http' => [ 'timeout' => 3600, // 设置1小时超时 'connect_timeout' => 60, ], ],
- SDK版本:确保你的AWS SDK版本支持
MultipartCopy类,Laravel 8+默认依赖的AWS SDK版本已包含该功能,若版本过低需执行composer update aws/aws-sdk-php更新。
内容的提问来源于stack exchange,提问作者Lokesh Mukeriya
相关产品推荐
相关产品推荐

