文件上传失败主因是表单未正确提交或验证配置错误:必须设enctype="multipart/form-data",name值与控制器严格一致,required需显式声明,mimes等规则格式精准,PHP及服务器上传限制需同步调优。

文件上传失败,90%不是代码写错,而是验证没过或验证本身配置有误。关键不在“怎么存”,而在“有没有真正收到、有没有被规则拦下”。先让文件进来,再谈存储。
表单和请求层必须过关
这是最底层的门槛,跨不过去,后续全白搭:
-
form 标签必须带
enctype="multipart/form-data"——漏一个字符,$request->file()就是null,验证器连文件都看不到 -
input 的
name值要和控制器里file('xxx')的字符串完全一致:大小写、下划线、空格都不能差(比如name="avatar "和file('avatar')就不匹配) - 多文件用数组语法:
name="photos[]"→ 对应$request->file('photos')(返回数组),别写成file('photos.0') - 临时验证是否真传过来了:在控制器开头加
dd($request->allFiles()),看输出是不是空数组
验证规则写法必须精准
规则写错,哪怕文件已上传,也会被拦在验证环节,报“类型不支持”或“必填项缺失”:
-
别在
mimes后加空格:写成'mimes: jpeg,jpg,png'是错的,正确是'mimes:jpeg,jpg,png' -
单个文件必须带
required|file前置校验,否则mimes或image规则不会触发 - 多文件上传不能只写
'files' => 'required|array',要写通配符:'files.*' => 'required|file|mimes:jpeg,png,pdf|max:2048' - 更安全的组合是:
'image' => 'required|file|image|mimetypes:image/jpeg,image/png,image/gif|max:2048'(mimetypes读文件头,防后缀伪装)
上传逻辑要显式指定磁盘
验证通过不代表文件能存对地方。默认 store() 走的是 local 磁盘,路径在 storage/app,这个目录 Web 服务器无法直接访问:
- 想让文件能通过
/storage/xxxURL 访问,必须用public磁盘:$request->file('image')->store('avatars', 'public') - 确保已执行
php artisan storage:link,使public/storage指向storage/app/public - 验证是否真存进去了:
Storage::disk('public')->exists('avatars/filename.jpg') - 避免用
getClientOriginalName()直接做文件名,推荐:uniqid('img_').'.'.$file->getClientOriginalExtension()
PHP 和 Web 服务器限制不能忽略
前端一切正常,但上传大文件失败?大概率卡在底层配置:
- 查 PHP 配置:
php -i | grep -E "(post_max_size|upload_max_filesize|file_uploads)" - Nginx 必须设
client_max_body_size,且值要大于post_max_size - Apache 若启用了
mod_security,可能静默拦截 multipart 请求,临时关闭可验证 - 上传后提示 “Unable to write”,先检查
storage/app和bootstrap/cache目录权限:sudo chown -R www-data:www-data storage/ bootstrap/cache/和sudo chmod -R 775 storage/ bootstrap/cache/


















