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

Laravel使用Maatwebsite/excel导入Excel图片并存库实现方法

Maatwebsite/Excel 导入带图片Excel存数据库实现方案

核心逻辑

Maatwebsite/Excel 默认的行数据读取逻辑仅解析单元格文本值,嵌入Excel的图片属于独立的Drawing绘图对象,不会自动挂载到$row->toArray()返回的数组中,因此直接读取$row['image_path']无法获取图片内容。

Excel示例

Excel示例截图

原有实现代码

<?php

namespace App\Imports;

use App\SubmissionDetail;
use Maatwebsite\Excel\Row;
use Maatwebsite\Excel\Concerns\OnEachRow;
use Maatwebsite\Excel\Concerns\WithHeadingRow;

class SubmissionDetailImport implements OnEachRow, WithHeadingRow
{
    protected $id;

    function __construct($id) {
            $this->id = $id;
    }

    public function onRow(Row $row)
    {
        $row = $row->toArray();

        $submissionDetails = SubmissionDetail::firstOrCreate(
            ['submission_id' => $this->id, 'nama_barang' => $row['nama_barang']],
            [
                'submission_id' => $this->id,
                'nama_barang' => $row['nama_barang'],
                'image_path' => $row['image_path'],
                'jumlah' => $row['jumlah'],
                'harga_satuan' => $row['harga_satuan'],
                'harga_total' => $row['harga_total'],
                'keterangan' => $row['keterangan'],
            ]
        );

        if (! $submissionDetails->wasRecentlyCreated) {
            $submissionDetails->update([
                'image_path' => $row['image_path'],
                'jumlah' => $row['jumlah'],
                'harga_satuan' => $row['harga_satuan'],
                'harga_total' => $row['harga_total'],
                'keterangan' => $row['keterangan'],
            ]);
        }
    }
}

落地实现步骤

  • 导入类新增实现WithDrawings接口,该接口为扩展包官方提供,专门用于解析Excel内嵌入的图片、绘图对象。
  • 新增类属性存储图片与所在行号的映射关系,在drawings()方法中遍历所有嵌入图片,记录图片二进制内容、后缀、对应行号。
  • 行处理逻辑中,根据当前行号匹配对应图片,将图片保存到本地存储目录,获取可访问的存储路径后写入数据库。

修正后可直接使用的代码

<?php

namespace App\Imports;

use App\SubmissionDetail;
use Maatwebsite\Excel\Row;
use Maatwebsite\Excel\Drawing;
use Maatwebsite\Excel\Concerns\OnEachRow;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithDrawings;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class SubmissionDetailImport implements OnEachRow, WithHeadingRow, WithDrawings
{
    protected $id;
    // 存储图片与行号的映射关系
    protected array $imageMap = [];

    public function __construct($id) {
        $this->id = $id;
    }

    /**
     * 注册图片解析处理器
     */
    public function drawings(): array
    {
        $imageMap = &$this->imageMap;
        return [
            new class($imageMap) implements Drawing {
                private array $imageMap;

                public function __construct(array &$imageMap)
                {
                    $this->imageMap = &$imageMap;
                }

                /**
                 * 每解析到一张嵌入图片就会触发该方法
                 * @param mixed $image 图片二进制内容
                 * @param string $path 图片原始文件名
                 * @param int $row 图片锚定的行号(从1开始计数)
                 * @param string $column 图片锚定的列名
                 */
                public function setImage($image, $path, $row, $column)
                {
                    $this->imageMap[$row] = [
                        'content' => $image,
                        'extension' => pathinfo($path, PATHINFO_EXTENSION) ?: 'png'
                    ];
                }
            }
        ];
    }

    public function onRow(Row $row)
    {
        $rowIndex = $row->getIndex();
        $rowData = $row->toArray();
        $imagePath = $rowData['image_path'] ?? null;

        // 匹配当前行对应的图片,保存到本地
        if (isset($this->imageMap[$rowIndex])) {
            $image = $this->imageMap[$rowIndex];
            $fileName = Str::random(20) . '.' . $image['extension'];
            // 保存到public磁盘的submission-images目录,执行php artisan storage:link后可通过web访问
            Storage::disk('public')->put('submission-images/' . $fileName, $image['content']);
            $imagePath = 'submission-images/' . $fileName;
        }

        $submissionDetails = SubmissionDetail::firstOrCreate(
            ['submission_id' => $this->id, 'nama_barang' => $rowData['nama_barang']],
            [
                'submission_id' => $this->id,
                'nama_barang' => $rowData['nama_barang'],
                'image_path' => $imagePath,
                'jumlah' => $rowData['jumlah'],
                'harga_satuan' => $rowData['harga_satuan'],
                'harga_total' => $rowData['harga_total'],
                'keterangan' => $rowData['keterangan'],
            ]
        );

        if (! $submissionDetails->wasRecentlyCreated) {
            $submissionDetails->update([
                'image_path' => $imagePath,
                'jumlah' => $rowData['jumlah'],
                'harga_satuan' => $rowData['harga_satuan'],
                'harga_total' => $rowData['harga_total'],
                'keterangan' => $rowData['keterangan'],
            ]);
        }
    }
}

注意事项

  • 代码基于Maatwebsite/Excel 3.1+版本编写,使用前请确认扩展包版本符合要求。
  • 首次使用public磁盘存储文件前,需要执行php artisan storage:link命令创建软链接,否则前端无法访问存储的图片。
  • 如果Excel中图片存在行偏移(比如图片锚定行和实际对应数据行差1-2行),只需要在匹配图片时给$rowIndex加减对应偏移值即可。
  • 如果单行存在多张图片,可以将$imageMap改为按行号+列名存储二维结构,分别匹配不同字段对应的图片。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 03:39:24