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); }
额外排查点
- 查看日志中
\Log::info($file_count)的输出值,确认是否为2,验证上传的文件数组是否被正确获取。 - 检查存储目录的权限,确保Laravel拥有写入多个文件的权限。
内容的提问来源于stack exchange,提问作者Betty
相关产品推荐
相关产品推荐

