You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel多图上传:如何在验证错误中显示文件名并优化展示

解决Laravel多图上传验证错误显示问题

一、让验证错误信息包含文件名

默认验证错误会以uploads.0这类索引标识错误文件,我们需要将其替换为对应上传文件的原始名称,步骤如下:

  1. 修改控制器验证失败后的错误处理逻辑
    在验证失败时,遍历错误信息并替换索引为文件名:

    if ($validator->fails()) {
        // 获取所有上传的文件
        $uploadedFiles = $request->file('uploads') ?? [];
        $customErrors = [];
        
        foreach ($validator->errors()->getMessages() as $field => $messages) {
            // 匹配uploads.N格式的字段
            if (preg_match('/^uploads\.(\d+)$/', $field, $matches)) {
                $index = $matches[1];
                // 获取对应文件的原始名称,不存在则显示"未知文件"
                $fileName = isset($uploadedFiles[$index]) ? $uploadedFiles[$index]->getClientOriginalName() : '未知文件';
                // 替换错误消息中的索引为文件名
                foreach ($messages as $msg) {
                    $customErrors[] = str_replace($field, $fileName, $msg);
                }
            } else {
                // 非上传字段的错误保持原样
                $customErrors = array_merge($customErrors, $messages);
            }
        }
        
        return redirect()->route('shipping.create')
            ->withErrors(['custom' => $customErrors])
            ->withInput();
    }
    
  2. (可选)优化错误消息模板
    在resources/lang/zh-CN/validation.php中添加更友好的自定义消息:

    'image' => ':attribute 必须是图片文件。',
    'mimes' => ':attribute 必须是以下类型的文件: :values。',
    

    替换后错误消息会变成类似"xxx.pdf 必须是图片文件。"的格式。

二、将错误提示显示在文件输入框下方

移除全局统一的错误警告框,改为在文件输入字段下方展示对应错误:

  1. 删除Blade中的全局错误警告框
    移除以下代码:

    @if (count($errors) > 0)
    <div class="alert alert-danger">
    <ul>
      @foreach ($errors->all() as $error)
         <li>{{ $error }}</li>
      @endforeach
    </ul>
    </div>
    @endif
    
  2. 在文件输入框下方添加错误展示代码
    在多文件输入字段(如<input type="file" name="uploads[]" multiple>)下方插入:

    <div class="error text-danger fs-6 fw-400">
        @if($errors->has('custom'))
            @foreach($errors->get('custom') as $error)
                <p>{{ $error }}</p>
            @endforeach
        @endif
    </div>
    
  3. 保留其他字段的错误显示逻辑
    其他字段(如shipping_code)的错误展示代码保持不变:

    @if($errors->has('shipping_code'))
    <div class="error text-danger fs-6 fw-400">{{ $errors->first('shipping_code') }}</div>
    @endif
    

完整控制器代码示例

public function store(Request $request) {
    $validator = Validator::make($request->all(),[
        'shipping_code' => 'required|string',
        'customer_name' => 'required|exists:users,id',
        'shipper_name' => 'nullable|exists:users,id',
        'shipping_details' => 'nullable|string',
        'pickup_date' => 'required|date',
        'delivery_date' => 'nullable|date',
        'driver_name' => 'required|exists:users,id',
        'driver_fee' => 'required|regex:/^\d+(\.\d{1,2})?$/',
        'transaction_fee' => 'required|regex:/^\d+(\.\d{1,2})?$/',
        'remarks' => 'nullable|string',
        'status' => 'required|in:0,1,2,3',
        'uploads' => 'required',
        'uploads.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
    ]);

    if ($validator->fails()) {
        $uploadedFiles = $request->file('uploads') ?? [];
        $customErrors = [];
        foreach ($validator->errors()->getMessages() as $field => $messages) {
            if (preg_match('/^uploads\.(\d+)$/', $field, $matches)) {
                $index = $matches[1];
                $fileName = isset($uploadedFiles[$index]) ? $uploadedFiles[$index]->getClientOriginalName() : '未知文件';
                foreach ($messages as $msg) {
                    $customErrors[] = str_replace($field, $fileName, $msg);
                }
            } else {
                $customErrors = array_merge($customErrors, $messages);
            }
        }
        return redirect()->route('shipping.create')
            ->withErrors(['custom' => $customErrors])
            ->withInput();
    } else{
        DB::transaction(function () use($request) {
            $exPd = explode(',',$request->driver_name);
            $driver_id = $exPd[0];

            $shipping = new Shipping();
            $shipping->shipping_code = $request->shipping_code;
            $shipping->customer_id = $request->customer_name;
            $shipping->shipper_id = $request->shipper_name;
            $shipping->driver_id = $driver_id;
            $shipping->shipping_details = $request->shipping_details;
            $shipping->pickup_date = convertDateToDB($request->pickup_date);
            $shipping->delivery_date = convertDateToDB($request->delivery_date);
            $shipping->driver_fee = $request->driver_fee;
            $shipping->transaction_amount = $request->transaction_fee;
            $shipping->remarks = $request->remarks;
            $shipping->status = $request->status;
            $shipping->created_at = date('Y-m-d H:i:s');
            $shipping->created_by = Auth::user()->id;

            $shipping->save();

            if($request->hasfile('uploads')) {
                foreach($request->file('uploads') as $file)
                {
                    $input['imagename'] = time().'.'.$file->extension();
                    $filePath = public_path('/uploads/shipping_transaction_images/');
                    $img = Image::make($file->path());
                    $img->resize(110, 110, function ($const) {
                        $const->aspectRatio();
                    })->save($filePath.$input['imagename']);
                    $imgData[] = $input['imagename'];
                    $fileModal = new ShippingImage();
                    $fileModal->shipping_id = $shipping->id;
                    $fileModal->image_type = 'pickup';
                    $fileModal->image_file = $input['imagename'];
                    $fileModal->save();
                }
            }
        });

        return redirect()->route('shippings.index')
                            ->with('success','Shipping Transaction Created Successfully');
    }
}

内容的提问来源于stack exchange,提问作者Baby Babai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:25:28