Laravel 10下利用maatwebsite/excel提取Excel图片并保存至磁盘
解决Laravel Excel读取每行图片并保存的问题
toArray方法无法直接提取Excel中的嵌入图片,需要通过自定义Import类结合Laravel Excel的事件机制来实现图片提取,以下是具体实现步骤:
1. 重构RecordImport类
修改你的RecordImport,实现ToCollection和WithHeadingRow(如果Excel带表头)接口,同时通过事件提取工作表内的所有图片:
use Maatwebsite\Excel\Concerns\ToCollection; use Maatwebsite\Excel\Concerns\WithHeadingRow; use Maatwebsite\Excel\Events\BeforeSheet; use Illuminate\Support\Collection; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; class RecordImport implements ToCollection, WithHeadingRow { private $images = []; public function collection(Collection $rows) { return $rows; } public function registerEvents(): array { return [ BeforeSheet::class => function(BeforeSheet $event) { /** @var Worksheet $sheet */ $sheet = $event->sheet->getDelegate(); $drawingCollection = $sheet->getDrawingCollection(); foreach ($drawingCollection as $drawing) { // 记录图片所在的单元格坐标(如E2、E3)和图片资源/路径 $this->images[$drawing->getCoordinates()] = $drawing; } }, ]; } public function getImages() { return $this->images; } }
2. 业务逻辑中匹配行与图片并保存
改用toCollection方法触发事件,然后根据行号匹配对应单元格的图片,保存到磁盘:
// 实例化Import类 $import = new RecordImport(); // 读取Excel并触发图片提取事件 $sheets = Excel::toCollection($import, $tempPathOfExcelFile); // 获取所有提取到的图片(键为单元格坐标) $allImages = $import->getImages(); foreach ($sheets as $sheet) { foreach ($sheet as $idx => $row) { // 计算当前行对应Excel的实际行号:带表头则索引+2,无表头则索引+1 $rowNumber = $idx + 2; // photo列是第5列,对应Excel的E列,拼接单元格坐标 $imageCell = 'E' . $rowNumber; if (isset($allImages[$imageCell])) { $drawing = $allImages[$imageCell]; $fileName = uniqid() . '.' . $drawing->getExtension(); $saveDir = storage_path('app/public/photos'); // 处理不同存储形式的图片 if ($drawing->getPath()) { // 图片以文件形式存在,直接复制 copy($drawing->getPath(), $saveDir . '/' . $fileName); } else { // 图片是嵌入的GD资源,生成文件 $imageResource = $drawing->getImageResource(); imagepng($imageResource, $saveDir . '/' . $fileName); imagedestroy($imageResource); } // 生成可访问的URL,用于存入数据库 $photoUrl = Storage::url('photos/' . $fileName); // 将$photoUrl关联到当前记录,比如$row['photo'] = $photoUrl } // 原有验证、插入数据库逻辑 // ... } }
3. 关键注意事项
- 确保
storage/app/public目录有写入权限,执行php artisan storage:link生成公共访问软链接 - 如果Excel不带表头,移除
WithHeadingRow接口,并将行号计算改为$rowNumber = $idx + 1 - 可根据需求调整存储磁盘(如阿里云OSS、AWS S3),只需修改
Storage::disk('xxx')即可
内容的提问来源于stack exchange,提问作者prueba prueba
相关产品推荐
相关产品推荐

