PHP中excel带图片数据导入

前提:有个需求需要实现带图片的excel数据导入数据库中,发现PHPExcel - Excel 操作库已经停止维护,在PHP8的版本中,有些语法不支持,报错一堆,改了一堆,又还有一堆。所以决定找个替代的扩展:phpoffice/phpspreadsheet

技术背景前提:

  1. ThinkPHP8.0
  2. php8.0.2nts
  3. "phpoffice/phpspreadsheet": "^1.20.0"

在composer.json中加入"phpoffice/phpspreadsheet": "^1.20.0"composer update,如果选择的phpoffice/phpspreadsheet版本不同,可能又有不同的坑存在,得进行一一排查。这里记录下。

实现步骤看代码注释部分,实现代码如下:

php 复制代码
    /**
     * 字母序列化为数字
     */
    public function ABC2decimal($abc)
    {
        $ten = 0;
        $len = strlen($abc);
        for ($i = 1; $i <= $len; $i++) {
            $char = substr($abc, 0 - $i, 1);//反向获取单个字符
            $int = ord($char);
            $ten += ($int - 65) * pow(26, $i - 1);
        }
        return $ten;
    }


    public function excel()
    {
        if ($file = request()->file('excel')) {
            try {
                $saveName = Filesystem::disk('public')->putFile('/static/upload/excels', $file);
                if (!is_file($saveName)) {
                    return json(['code' => 1, 'msg' => '文件不存在', 'data' => null]);
                }
                $ext = pathinfo($saveName, PATHINFO_EXTENSION);
                // xls不支持图片导入
                // if (!in_array($ext, ['xlsx', 'xls'])) {
                if (!in_array($ext, ['xlsx'])) {
                    return json(['code' => 1, 'msg' => '文件类型不正确', 'data' => null]);
                }
                // 有两种格式,xlsx和xls
                if ($ext == 'xlsx') {
                    $objReader = IOFactory::createReader('Xlsx');
                } else {
                    $objReader = IOFactory::createReader('Xls');
                }
                // 图片保存路径
                $imageFilePath1 = root_path() . '/public/'; // 图片保存目录
                $imageFilePath2 = 'static/upload/images/' . date("Ymd") . '/';
                $imageFilePath = $imageFilePath1 . $imageFilePath2;
                if (!file_exists($imageFilePath)) {
                    mkdir("$imageFilePath", 0777, true);
                }
                // 载入excel文件
                $excel = $objReader->load($saveName);
                // 读取第一张表
                $sheet = $excel->getActiveSheet();
                // 读取总行数
                $highestRow = $sheet->getHighestRow();
                // 读取第一张表转换成数组
                $data = $sheet->toArray();

                // 处理图片
                foreach ($sheet->getDrawingCollection() as $drawing) {
                    list($startColumn, $startRow) = Coordinate::coordinateFromString($drawing->getCoordinates());
                    $imageFileName = $drawing->getIndexedFilename();  // 获取文件名
                    switch ($drawing->getExtension()) {
                        case 'jpg':
                        case 'jpeg':
                            $source = imagecreatefromjpeg($drawing->getPath());
                            imagejpeg($source, $imageFilePath . $imageFileName);
                            break;
                        case 'gif':
                            $source = imagecreatefromgif($drawing->getPath());
                            imagegif($source, $imageFilePath . $imageFileName);
                            break;
                        case 'png':
                            $source = imagecreatefrompng($drawing->getPath());
                            imagepng($source, $imageFilePath . $imageFileName);
                            break;
                    }
                    $startColumn = $this->ABC2decimal($startColumn);
                    $data[$startRow - 1][$startColumn] = $imageFilePath2 . $imageFileName;
                }

                // 数据写入数据库
                $add_data = [];
                for ($i = 1; $i <= $highestRow - 1; $i++) {
                    $add_data[$i]['institution'] = $data[$i][0];
                    $add_data[$i]['name'] = $data[$i][1];
                    $add_data[$i]['sex'] = $data[$i][2];
                    $add_data[$i]['phone'] = $data[$i][3];
                    $add_data[$i]['id_type'] = $data[$i][4];
                    $add_data[$i]['id_no'] = $data[$i][5];
                    $add_data[$i]['occupation'] = $data[$i][6];
                    $add_data[$i]['job'] = $data[$i][7];
                    $add_data[$i]['skill_level'] = $data[$i][8];
                    $add_data[$i]['certificate_no'] = $data[$i][9];
                    $add_data[$i]['create_time'] = $data[$i][10];
                    $add_data[$i]['start_time'] = $data[$i][11];
                    $add_data[$i]['end_time'] = $data[$i][12];
                    $add_data[$i]['path'] = $data[$i][13];
                }

                // 数据插入数据库
                $success_count = Db::table('certificate')->insertAll($add_data);
                if ($success_count > 0) {
                    return json(['code' => 0, 'msg' => '数据插入成功', 'data' => null]);
                } else {
                    return json(['code' => 1, 'msg' => '数据插入失败', 'data' => null]);
                }
            } catch (\Exception $e) {
                return json(['code' => 1, 'msg' => $e->getMessage(), 'data' => null]);
            }
        } else {
            return json(['code' => 1, 'msg' => '上传文件不能为空', 'data' => null]);
        }
    }
相关推荐
JaguarJack1 天前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo1 天前
FrankenPHP 原生支持 Windows 了
后端·php
JaguarJack2 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo2 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack3 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay4 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954484 天前
CTF 伪协议
php
BingoGo6 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack6 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo7 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php