表单必须设置enctype="multipart/form-data"且name属性与request()->file()参数一致;storeas()可保留原扩展名但需过滤恶意文件名;mimes验证依赖finfo扩展和mime类型而非后缀;php和nginx需同步调整上传限制。

上传文件时 request()->file() 返回 null 怎么办
Laravel 里拿不到上传的文件,八成是表单没写对。最常见的是漏了 enctype="multipart/form-data",浏览器直接把文件字段当普通文本丢掉了。
- 表单必须带
enctype="multipart/form-data",哪怕只传一个文件也得加 -
<input type="file">的name属性值,要和request()->file('xxx')里的字符串完全一致(区分大小写) - 如果用了数组式命名如
name="photos[]",request()->file('photos')会返回数组,不能用->store()直接调用,得遍历
示例错误写法:
<form method="POST">→ 缺 enctype,必 null
正确写法:
<form method="POST" enctype="multipart/form-data">
Laravel 上传后文件名被重命名,怎么保留原名
store() 默认用哈希名,安全但丢了原始信息。storeAs() 才能控制路径和文件名,但注意:它不自动处理中文或特殊字符,直接传 $request->file('avatar')->getClientOriginalName() 可能出错。
- 原始文件名要用
getClientOriginalName(),不是getClientOriginalExtension() - 中文名建议过滤或转拼音,否则在某些服务器(如 Nginx + fastcgi)下可能 502 或写入失败
- 更稳妥的做法是拼接唯一前缀 + 原始扩展名:
$file->storeAs('avatars', uniqid() . '.' . $file->getClientOriginalExtension()) - 别直接用
getClientOriginalName()当路径,用户可能传../../etc/passwd这种恶意名字,Laravel 会自动过滤,但别依赖它做校验
验证上传文件大小、类型失败,mimes 规则总不生效
mimes:jpg,png 看似简单,实际依赖服务器的 finfo 扩展和 MIME 类型映射表,不是看后缀名。很多本地环境(尤其是 Windows + XAMPP)缺配置,导致明明是 .png 却被识别为 application/octet-stream。
- 先确认
php -m | grep fileinfo输出有fileinfo -
mimes对应的其实是文件“内容类型”,不是扩展名;查 Laravel 文档的mimes映射表,比如png对应image/png,不是png字符串本身 - 更可靠的方式是组合使用:
'mimetypes:image/jpeg,image/png', 'max:2048' - 开发时用
dd($file->getMimeType())看实际识别结果,比猜规则更直接
上传大文件(比如 >2MB)直接 413 或 500,怎么调 PHP 和 Nginx 限制
Laravel 层面的验证(如 max:10240)根本没机会执行——请求在到达 PHP 前就被 Web 服务器拦下了。
- PHP 需改两个值:
upload_max_filesize和post_max_size(后者必须 ≥ 前者),改完重启 PHP-FPM 或 Apache - Nginx 要加
client_max_body_size 20M;到server或location块里,否则 413 Request Entity Too Large - Laravel 的
php.ini配置和 Nginx 配置必须匹配,比如你设了upload_max_filesize = 16M,但 Nginx 还是默认 1M,照样卡在网关层 - 开发环境常用 Valet / Homestead,它们各自有配置入口,别只改
php.ini忘了配 Nginx
上传这件事,真正卡住人的从来不是 Laravel 的 API,而是 HTTP 协议层、Web 服务器、PHP 运行时这三层的协同。少调一个参数,就停在某个 4xx 或 5xx 里,连 request()->file() 都摸不到。










