Laravel 8注册环节如何实现多附件上传与存储功能?
Laravel 8 注册环节文件上传功能可落地方案
前置必做修正(90%的上传失效问题都源于这步)
- 表单必须添加
enctype="multipart/form-data"属性,否则文件字段不会被PHP正常接收。修改对应Blade表单的开头标签:原表单(缺属性):
<form method="POST" action="{{ route('register') }}">
修改后:<form method="POST" action="{{ route('register') }}" enctype="multipart/form-data"> - 确认3个文件上传字段的name属性与后端逻辑一一对应。当前提供的Blade片段仅包含2个字段(
kra_pindoc、id_carddoc),补充第三个字段(以profile_photo为例)的标签时,保证id与name属性一致:<div class="col-sm-3"> <label for="profile_photo">Attach Profile Photo</label> <input type="file" class="form-control-file" id="profile_photo" name="profile_photo"> </div>
数据库表结构调整
实现文件信息入库,需先给users表新增对应字段:
- 执行命令生成迁移文件:
php artisan make:migration add_upload_fields_to_users_table - 修改迁移文件的
up方法:public function up() { Schema::table('users', function (Blueprint $table) { // 存储KRA证件文件相关信息 $table->string('kra_pindoc_path')->nullable()->comment('KRA证件存储路径'); $table->string('kra_pindoc_name')->nullable()->comment('KRA证件原始文件名'); $table->unsignedBigInteger('kra_pindoc_size')->nullable()->comment('KRA证件文件大小(字节)'); // 存储身份证文件相关信息 $table->string('id_carddoc_path')->nullable()->comment('身份证存储路径'); $table->string('id_carddoc_name')->nullable()->comment('身份证原始文件名'); $table->unsignedBigInteger('id_carddoc_size')->nullable()->comment('身份证文件大小(字节)'); // 存储头像文件相关信息 $table->string('profile_photo_path')->nullable()->comment('头像存储路径'); $table->string('profile_photo_name')->nullable()->comment('头像原始文件名'); $table->unsignedBigInteger('profile_photo_size')->nullable()->comment('头像文件大小(字节)'); }); } - 执行迁移同步表结构:
php artisan migrate
模型层调整
修改User模型的$fillable属性,将新增的文件字段加入允许批量赋值的列表,否则文件信息无法写入数据库:
protected $fillable = [ 'surname', 'middle_name', 'first_name', 'email', 'password', 'username', // 新增文件相关字段 'kra_pindoc_path', 'kra_pindoc_name', 'kra_pindoc_size', 'id_carddoc_path', 'id_carddoc_name', 'id_carddoc_size', 'profile_photo_path', 'profile_photo_name', 'profile_photo_size', ];
校验规则调整
修改RegisterController中的validator方法,为3个文件字段添加合法性校验:
- 校验逻辑:文件默认非必填(如需强制上传,移除规则中的
nullable)、允许格式为pdf/jpg/png、单文件最大2MB
protected function validator(array $data) { return Validator::make( $data, [ 'surname' => 'required|string|max:255', 'middle_name' => 'required|string|max:255', 'first_name' => 'required|string|max:255', 'email' => 'required|email|max:255|unique:users', 'password' => 'required|min:8|confirmed', 'password_confirmation' => 'required|same:password', 'username' => 'required|string|max:255|unique:users|alpha_dash', // 新增文件字段校验规则 'kra_pindoc' => 'nullable|file|mimes:pdf,jpg,png|max:2048', 'id_carddoc' => 'nullable|file|mimes:pdf,jpg,png|max:2048', 'profile_photo' => 'nullable|file|mimes:jpg,png|max:2048', ] ); }
文件存储逻辑调整
修改RegisterController中的create方法,实现文件存储到指定目录、文件信息同步入库的逻辑:
- 存储目录默认设为
storage/app/public/register_uploads/,需先执行命令生成public目录软链接:php artisan storage:link,保证上传的文件可被正常访问
protected function create(array $data) { // 初始化文件信息默认值 $uploadData = [ 'kra_pindoc_path' => null, 'kra_pindoc_name' => null, 'kra_pindoc_size' => null, 'id_carddoc_path' => null, 'id_carddoc_name' => null, 'id_carddoc_size' => null, 'profile_photo_path' => null, 'profile_photo_name' => null, 'profile_photo_size' => null, ]; // 遍历处理3个上传字段 $uploadFields = ['kra_pindoc', 'id_carddoc', 'profile_photo']; foreach ($uploadFields as $field) { // 判断当前字段是否存在上传文件 if (request()->hasFile($field)) { $file = request()->file($field); // 生成唯一文件名,避免重名覆盖 $fileName = time().'_'.\Str::random(10).'.'.$file->getClientOriginalExtension(); // 存储到指定公共目录 $storePath = $file->storeAs('register_uploads', $fileName, 'public'); // 写入文件信息到待存储数组 $uploadData[$field.'_path'] = $storePath; $uploadData[$field.'_name'] = $file->getClientOriginalName(); $uploadData[$field.'_size'] = $file->getSize(); } } // 合并原有用户数据与上传文件信息,创建用户记录 return User::create(array_merge([ 'surname' => $data['surname'], 'middle_name' => $data['middle_name'], 'first_name' => $data['first_name'], 'email' => $data['email'], 'username' => $data['username'], 'password' => Hash::make($data['password']), ], $uploadData)); }
常见踩坑排查
- 给storage目录配置正确的读写权限:
chmod -R 775 storage - 如遇大文件上传超限,修改php.ini中的
upload_max_filesize与post_max_size参数,与校验规则中的大小限制保持一致 - 无需修改重写的
register方法逻辑,因为create方法会自动处理所有上传的文件数据
内容的提问来源于stack exchange,提问作者Amos
相关产品推荐
相关产品推荐

