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

Laravel 5.3.31多图上传异常:仅单张图片保存成功求助

多图上传仅保存单张的问题排查与解决

问题描述

在Laravel 5.3.31项目中实现多图上传,已设置文件输入框的multiple属性并命名为数组形式images[],表单也配置了enctype="multipart/form-data",但实际选择2张图片上传后,最终仅1张被保存。

相关代码

控制器字段配置

[
    'name' => 'images[]',
    'label' => '',
    'widget' => 'file',
    'widget_attr' => [
        'class' => 'form-control',
        'multiple' => true,
    ],
    // 'widget_only' => null,
    'callback' => function($field, $row){
        if ($row && $row->estimate_status_id == 5) {
            $field['widget'] = 'text';
        }
        $files = \Storage::files('westims/pictures/' . $row->site_id . '/' . $row->id);

        if (count($files) > 0){
            $field['preview'] = '';
            foreach ($files as $file){
                $field['preview'] .= ' <a href="' . url("admin/docs?path=$file") . '" target="_blank"><img src="' .  url("admin/docs?path=$file") . '" style="max-height:100px"/>  </a>';
            }
        } else {
            $field['preview'] = trans('westims.no-images');
        }

        if(count($files) >=30 ) {
            $field['widget'] = 'text';
        }

        return $field;
    },
    'column_span' => $this->detailColumns,
],

图片保存逻辑

if (Input::hasFile('images')){
    $file_count = count(\Storage::files('westims/pictures/' . $row->site_id . '/' . $row->id));
    if ($file_count < 30){
        $files = Input::file('images');

        if(is_array($files)){
            $file_count = count($files);
            \Log::info($file_count);
            foreach($files as $file) {
                $filename = $file->getClientOriginalName();
                \Log::info($filename);
                $file->storeAs('westims/pictures/' . $row->site_id . '/' . $row->id, $filename);
            }
        } else {
            $filename = str_pad($file_count, 3, '0', STR_PAD_LEFT);
            Input::file('images')->storeAs('westims/pictures/' . $row->site_id . '/' . $row->id, $filename);
        }

问题原因

核心问题是文件名重复导致文件覆盖:

  • 代码中使用$file->getClientOriginalName()获取原文件名作为存储文件名,若上传的多张图片存在同名情况,后续上传的文件会直接覆盖之前的文件,最终仅保留最后一张。
  • 查看\Log::info($filename)的输出即可验证:如果日志显示多个相同文件名,就说明是覆盖问题。

解决方案

方案1:生成唯一文件名(推荐)

使用时间戳拼接原文件名,或者Laravel自带的hashName()方法生成唯一文件名,彻底避免覆盖:

foreach($files as $file) {
    // 方式1:时间戳+原文件名,保留原名称辨识度
    $filename = time() . '_' . $file->getClientOriginalName();
    // 方式2:Laravel自带的唯一哈希文件名,完全避免重复
    // $filename = $file->hashName();
    \Log::info($filename);
    $file->storeAs('westims/pictures/' . $row->site_id . '/' . $row->id, $filename);
}

方案2:保留原文件名并处理重复

如果必须保留原文件名,可检查文件是否已存在,存在则添加递增后缀:

foreach($files as $file) {
    $originalName = $file->getClientOriginalName();
    $filename = $originalName;
    $storagePath = 'westims/pictures/' . $row->site_id . '/' . $row->id;
    
    // 循环检查文件是否存在,存在则添加递增后缀
    $counter = 1;
    while(\Storage::exists($storagePath . '/' . $filename)) {
        $extension = pathinfo($originalName, PATHINFO_EXTENSION);
        $nameWithoutExt = pathinfo($originalName, PATHINFO_FILENAME);
        $filename = "{$nameWithoutExt}({$counter}).{$extension}";
        $counter++;
    }
    
    $file->storeAs($storagePath, $filename);
}

额外排查点

  1. 查看日志中\Log::info($file_count)的输出值,确认是否为2,验证上传的文件数组是否被正确获取。
  2. 检查存储目录的权限,确保Laravel拥有写入多个文件的权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 18:50:24