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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:18:31