php 实现 word 转为 图片

项目需求是这样的:用户签订合同,并读取用户信息生成合同,将合同保存为png图片保存

环境:windows(2012,linux要配置java环境,偷懒)+ apache(2.4.48) + php(7.1) + mysql(5.5.62)

框架:tp5.0.24,网站目录在public下面,环境直接用宝塔塔建的,phpenv 本地测试了也可以,其他的没有测试

第一步:向word写入用户信息

1. 将 PhpOffice 整个文件夹复制到 extend 文件夹下(如下图)


2. 接下来就是代码了,直接上:

    // 文字写入world
    public function word_write()
    {
        import('PhpOffice\PhpWord\TemplateProcessor', '.php');

        // 1.创建模板对象
        $temp_path = $_SERVER['DOCUMENT_ROOT'] . '/xieyi_fuwu_copy.docx';   // 模板文件路径
        $document = new \PhpOffice\PhpWord\TemplateProcessor($temp_path);

        // 2.插入数据 : word中的变量 ${name} ${idcard} ${phone} {$time}
        $data = [
            ['key' => 'name', 'value' => '小度哇'],
            ['key' => 'idcard', 'value' => '341022188810222345'],
            ['key' => 'phone', 'value' => '18888888888'],
            ['key' => 'time', 'value' => date('Y年m月d日')],
        ];
        foreach ($data as $k => $v) {
            $document->setValue($v['key'], $v['value']);
        }

        // 3.保存文件
        $file_path = $_SERVER['DOCUMENT_ROOT'] . '/file/' . date('Ymd');
        if (!file_exists($file_path)) {
            mkdir($file_path, '0777');
        }
        $document->saveAs($file_path.'/'.time().'.docx');
    }

第二步:world 转为 pdf

  1. 修改php.ini
    添加:extension=php_com_dotnet.dll
    去除注释:com.allow_dcom = true
    重启php环境

  2. 安装office,一定要安装office,(office 2007 需要手动安装 Microsoft Save as PDF and XPS)【https://files-cdn.cnblogs.com/files/XiaoMingBlingBling/SaveAsPDFandXPS.rar】

  3. 配置office组件服务:win+R打开运行菜单,输入dcomcnfg
    找到 [组件服务] — [计算机]— [我的电脑] — [DCOM配置] — [Microsoft Wrord 97-2003文档]
    右键 [Microsoft Wrord 97-2003文档] 设置属性 [标识] 为 [交互式用户]

  4. 可以写代码了

	// world 转为 pdf
    function index3()
    {
        $filenamedoc = $_SERVER['DOCUMENT_ROOT'] . '/xieyi_fuwu_copy.docx';	// word 文件地址
        $filenamepdf = $_SERVER['DOCUMENT_ROOT'] . '/xieyi_fuwu_copy.pdf';		// 生成的 PDF 文件保存地址

        if (!file_exists($filenamedoc )) {
            return 'word原文件不存在';
        }

        // 删除已有同名文件
        if (file_exists($filenamepdf)) {
            unlink($filenamepdf);
        }

        // 执行转换操作
        $word = new \COM("word.Application") or die("Could not initialise Object");
        $word->Documents->Open($filenamedoc);
        $word->ActiveDocument->ExportAsFixedFormat($filenamepdf, 17, false, 0, 0, 0, 0, 7, true, true, 2, true, true, false);
        $word->Quit(false);
        unset($word);

        return '转换成功';
    }

第三步:PDF 转为图片

  1. 安装 ImageMagic 扩展,可以参考:https://www.cnblogs.com/jinxiblog/p/8053008.html,这个链接里面写的,我的就是按照这个来的,宝塔的话就不需要了,直接在 [软件管理]—[php7.1]—[安装扩展] 找到imagemagick,直接安装就可以了,如下图
    在这里插入图片描述

  2. 安装 ghostscript.exe (ghostscript.exe安装好之后需要添加到环境变量里面,并且将 gs9.54.0\bin\gswin64.exe 复制一份修改为gs.exe),我的上篇文章里面有提到过 ghostscript.exe 的坑,采坑的可以参考下

  3. 上代码

	// pdf 转为图片
    public function index4()
    {
        $from_path = $outPath = $_SERVER['DOCUMENT_ROOT'] . '/xieyi_fuwu_copy.pdf';  // PDF文件位置
        $target_path = $_SERVER['DOCUMENT_ROOT'] . '/xieyi_fuwu_copy.png';     // 图片文件位置
        try {
            $img = new Imagick();
            $img->setCompressionQuality(100);
            $img->setResolution(120, 120);
            $img->readImage($from_path);

            $canvas = new Imagick();
            $imgNum = $img->getNumberImages();

            foreach ($img as $k => $sub) {
                $sub->setImageFormat('png');
                $sub->stripImage();
                $sub->trimImage(0);
                $width = $sub->getImageWidth() + 10;
                $height = $sub->getImageHeight() + 10;
                if ($k + 1 == $imgNum) $height += 10;
                $canvas->newImage($width, $height, new ImagickPixel('white'));
                $canvas->compositeImage($sub, Imagick::COMPOSITE_DEFAULT, 5, 5);
            }

            $canvas->resetIterator();

            $canvas->appendImages(true)->writeImage($target_path);
            return '转化成功';
        } catch (\Exception $e) {
            return '转化失败:'.$e->getMessage();
        }
    }

第四步:添加签名

这里我直接用tp添加图片水印的方式处理了

	// 添加签名
    public function add_sign()
    {
        $image = \think\Image::open($_SERVER['DOCUMENT_ROOT'] . '/xieyi_fuwu_copy.png');
        $image->water($_SERVER['DOCUMENT_ROOT'].'/qianming.png')->save($_SERVER['DOCUMENT_ROOT'].'/xieyi_fuwu_copy2.png');
    }

第五步:整合

最后,整合了上述代码,封装成类,直接上代码,我就放在了index模块下面了,放在其他地方及得改命名空间,上代码

<?php
/* Author: kaolagogo  Create time: 2021/9/9 0008 17:02 */

namespace app\index\controller;

use Imagick;
use ImagickPixel;

class Word2img
{
    protected $sign_img;    // 签名图片
    protected $user_id;     // 用户ID
    protected $file_name;   // 统一保存的文件名,不含文件后缀
    protected $data;        // word 文档中需要替换的参数
    
    public function __construct($sign_img, $user_id, $data)
    {
        $this->sign_img = $sign_img;
        $this->user_id = $user_id;
        $this->file_name = $user_id . time();
        $this->data = $data;
    }

    public function get_img()
    {
        $save_path = $this->word_write();
        if (!$save_path) {
            return json_encode(['code' => -1, 'msg' => '文字写入word失败']);
        }

        $pdf_path = $this->word2pdf($save_path);
        if ($pdf_path == -1) {
            return json_encode(['code' => -1, 'msg' => 'world转为pdf失败']);
        }

        $img_path = $this->pdf2img($pdf_path);
        if ($img_path == -1) {
            return json_encode(['code' => -1, 'msg' => 'pdf转为图片失败']);
        }

        $age_path = $this->add_water($img_path);
        if ($age_path == -1) {
            return json_encode(['code' => -1, 'msg' => '添加签名失败']);
        }

        return json_encode(['code' => 1, 'msg' => '生成签名图片成功', 'data' => $age_path]);
    }

    // 文字写入word
    public function word_write()
    {
        // ${name} ${idcard} ${phone} ${time}

        import('PhpOffice\PhpWord\TemplateProcessor', '.php');

        // 1.创建模板对象
        $temp_path = $_SERVER['DOCUMENT_ROOT'] . '/temp/agreement_free.docx';   // 模板文件路径
        $document = new \PhpOffice\PhpWord\TemplateProcessor($temp_path);

        // 2.插入数据
        foreach ($this->data as $k => $v) {
            $document->setValue($v['key'], $v['value']);
        }

        // 3.保存文件
        $file_path = $_SERVER['DOCUMENT_ROOT'] . '/file/' . date('Ymd');
        if (!file_exists($file_path)) {
            mkdir($file_path, '0777', true);
        }

        $save_path = $file_path . '/' . $this->file_name . '.docx';
        $document->saveAs($save_path);

        return $save_path;
    }

    // world 转为 pdf
    function word2pdf($word_path)
    {
        if (!file_exists($word_path)) {
            return -1;
        }

        $pdf_file = $_SERVER['DOCUMENT_ROOT'] . '/file/' . date('Ymd');        // pdf 存储目录
        if (!file_exists($pdf_file)) {
            mkdir($pdf_file, 0777, true);
        }

        // 删除已有同名文件
        $pdf_path = $pdf_file . '/' . $this->file_name . '.pdf';
        if (file_exists($pdf_path)) {
            unlink($pdf_path);
        }

        // 执行转换操作
        $word = new \COM("word.Application") or die("Could not initialise Object");
        $word->Documents->Open($word_path);
        $word->ActiveDocument->ExportAsFixedFormat($pdf_path, 17, false, 0, 0, 0, 0, 7, true, true, 2, true, true, false);
        $word->Quit(false);
        unset($word);

        return $pdf_path;
    }

    // pdf 转为图片
    public function pdf2img($pdf_path)
    {
        if (!file_exists($pdf_path)) {
            return -1;
        }

        $img_file = $_SERVER['DOCUMENT_ROOT'] . '/file/' . date('Ymd');        // img 存储目录
        if (!file_exists($img_file)) {
            mkdir($img_file, 0777, true);
        }

        $img_path = $img_file . '/' . $this->file_name . '.png';    // 图片文件位置
        try {
            $img = new Imagick();
            $img->setCompressionQuality(100);
            $img->setResolution(120, 120);
            $img->readImage($pdf_path);

            $canvas = new Imagick();
            $imgNum = $img->getNumberImages();

            foreach ($img as $k => $sub) {
                $sub->setImageFormat('png');
                $sub->stripImage();
                $sub->trimImage(0);
                $width = $sub->getImageWidth() + 20;
                $height = $sub->getImageHeight() + 100;
                if ($k + 1 == $imgNum) $height += 10;
                $canvas->newImage($width, $height, new ImagickPixel('white'));
                $canvas->compositeImage($sub, Imagick::COMPOSITE_DEFAULT, 5, 5);
            }

            $canvas->resetIterator();
            $canvas->appendImages(true)->writeImage($img_path);
        } catch (\Exception $e) {
            return -1;
        }

        return $img_path;
    }

    // 图片添加水印
    public function add_water($img_path)
    {
        if (!file_exists($img_path)) {
            return -1;
        }

        $date = date('Ymd');
        $save_file = $_SERVER['DOCUMENT_ROOT'] . '/file/' . $date;        // 添加水印后 img 存储目录
        if (!file_exists($save_file)) {
            mkdir($save_file, 0777, true);
        }

        // 给原图左上角添加水印并保存water_image.png
        $water_path = $_SERVER['DOCUMENT_ROOT'] . $this->sign_img;      // 水印图片位置,绝对路径
        if (!file_exists($water_path)) {
            return -1;
        }

        $save_path = $save_file . '/' . $this->file_name . '_end.png';    // 图片文件位置
        $image = \think\Image::open($img_path);
        $image->water($water_path, \think\Image::WATER_SOUTHWEST)->save($save_path);

        // return $save_path;       // 绝对路径
        return '/file/' . $date. '/' . $this->file_name . '_end.png';   // 返回相对路径
    }
}

调用代码

	function get_img()
    {
        $sign_img = '你的签名图片路径';
        $user_id = 1;
        $user_data = [
            ['key' => 'name', 'value' => '十三'],
            ['key' => 'idcard', 'value' => '341022199909092525'],
            ['key' => 'phone', 'value' => '18888888888'],
            ['key' => 'time', 'value' => date('Y年m月d日')],
        ];
        $word2img = new Word2img($sign_img, $user_id, $user_data);
        $get_agreement_img = json_decode($word2img->get_img(), true);
        if ($get_agreement_img['code'] != 1) {
            return ajax_return(-1, $get_agreement_img['msg']);
        }
        $agreement_img = $get_agreement_img['data'];
    }

注意,用宝塔搭建环境的话,防跨站攻击一定不要勾选,不要勾选,不要勾选。。。。。。在这里插入图片描述

结束

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值