Laravel升级至9后调用S3取文件报无法获取file_size错误如何解决
问题诱发原因
Laravel 9 底层依赖的文件系统抽象包 Flysystem 从 Laravel 5.8 时期使用的 1.x 版本升级到了 3.x 版本,S3 存储适配器的响应生成逻辑发生了不兼容变更:调用response()方法生成文件HTTP响应时,默认会先发起HeadObject请求拉取文件元数据(包含file_size、mime_type等字段),用来填充标准响应头。以下三类场景都会触发该报错:
- 权限配置缺失:Laravel 5.8 时期的Flysystem 1版本调用
response()时不会主动发起HeadObject请求,仅需要s3:GetObject权限即可正常运行,升级后新增的HeadObject请求要求IAM账号额外配置s3:HeadObject权限,没配权限就会拉取元数据失败。 - 路径/基础配置错误:升级后Flysystem 3不会自动过滤文件路径的多余前导斜杠,如果s3磁盘的
root配置、传入的$file_path带了多余斜杠,或者region、endpoint、bucket配置填错,会导致最终请求的文件路径不存在,自然无法获取文件大小。 - 第三方兼容存储适配问题:如果使用的是非AWS官方的S3兼容存储(比如MinIO、各类云厂商的对象存储兼容S3接口),旧版本的存储适配器没有适配Flysystem 3的元数据拉取逻辑,无法正常返回file_size字段。
修复方案
按优先级依次尝试以下方案即可解决:
- 基础校验排查:先通过AWS CLI或官方SDK测试当前密钥是否能正常访问目标路径文件、拉取元数据;打印
Storage::disk('s3')->path($file_path)确认最终拼接的文件路径没有多余斜杠、前缀错误,和实际存储的文件路径完全匹配。 - 全局配置兼容旧行为:在
config/filesystems.php的s3磁盘配置数组中加入'disable_asserts' => true,该配置是Flysystem 3官方提供的兼容项,开启后会关闭自动拉取元数据做校验的逻辑,调用response()时直接返回文件流,和Laravel 5.8时期的运行逻辑完全一致,原有业务代码不需要做任何修改即可正常运行。 - 手动构建响应:如果不想修改全局配置,可以替换原有
response()的调用逻辑,直接读取文件内容手动构建响应,跳过自动拉取元数据的步骤,示例代码如下:
$fileContent = Storage::disk('s3')->get($file_path); return response($fileContent, 200) ->header('Content-Type', Storage::disk('s3')->mimeType($file_path));
- 升级第三方适配器:如果使用第三方S3兼容存储,将对应的存储适配器包升级到支持Flysystem 3的版本即可。
内容的提问来源于stack exchange,提问作者Nadiya
相关产品推荐
相关产品推荐

