文件上传必须设置enctype="multipart/form-data",否则request()->file()返回null;storeAs()自动处理路径和唯一命名,move()需绝对路径且目录存在;图片验证必用image规则而非仅mimes;访问URL应统一用Storage::url()配合public磁盘。

文件上传前必须检查 enctype="multipart/form-data"
表单没设对编码类型,request()->file() 一定返回 null,连错误都不会报——Laravel 直接当普通字段处理。这不是 Laravel 的 bug,是浏览器根本没把文件发过来。
常见踩坑点:
- 用
Form::open()时漏传['files' => true] - 手写
<form></form>标签但只写了method="POST",忘了加enctype - Vue/React 前端用 axios 提交时,没用
FormData实例,而是直接传 JSON 对象
storeAs() 和 move() 别混用
storeAs() 是 Laravel 封装的快捷方法,自动处理路径拼接、目录创建、唯一文件名(默认开启);move() 是底层 PHP 的 move_uploaded_file() 封装,不做任何额外处理,路径必须绝对且目录得提前存在。
典型问题场景:
- 用
$request->file('avatar')->move('uploads', 'test.jpg'),结果报错Failed to move uploaded file—— 因为uploads目录不存在,或路径是相对路径 - 想保留原文件名却用了
storeAs('avatars', $request->file('avatar')->getClientOriginalName()),没加哈希前缀,可能被覆盖或引发安全风险 -
storeAs()默认存到storage/app/下,如果配了'public' => 'local'且想通过 URL 访问,记得先运行php artisan storage:link
图片验证不能只靠 mimes,还得用 image 规则
mimes:jpeg,jpg,png,gif 只校验文件扩展名和 MIME 类型头,容易被绕过;image 规则会真正调用 GD 或 Imagick 读取文件头,确认它真是图片。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
实操建议:
- 必加
'avatar' => 'required|image|mimes:jpeg,jpg,png,gif|max:2048',image放前面,失败更快 -
max:2048是 KB 单位,不是 MB,写成max:2会失效 - 上传 .php 文件改后缀为 .jpg?
image规则能拦住;只用mimes拦不住
本地保存后生成可访问 URL 要走 Storage::url()
直接拼 /storage/xxx.jpg 路径是错的——这个路径对应的是 public/storage 符号链接指向的 storage/app/public,但你存的位置未必在这。
比如你用 storeAs('temp', 'xxx.jpg'),文件实际在 storage/app/temp/xxx.jpg,这个目录默认不公开。要让它能被访问,只有两个办法:
- 存到
public磁盘(配置里设'disk' => 'public'),再用Storage::url('xxx.jpg')→ 返回/storage/xxx.jpg - 或者用
url('/storage/temp/xxx.jpg')手动拼,但前提是你要确保 web 服务器(Nginx/Apache)已把/storage路由映射到storage/app,这非常规、不推荐
最稳的路:统一走 public 磁盘 + Storage::url(),别自己造路径

















