php实现 word 转换 pdf,laravel框架 word 转 pdf,php 代码将 word 转换为 pdf

一、软件及版本

  • php 7.4

  • laravel 8.5


二、laravel 使用到的扩展,需要使用 composer来安装

  • phpoffice/phpword:^1.2

  • dompdf/dompdf:^2.0


三、场景描述:

     由业务同事提供固定的 word 模版,从数据库中获取数据。将文字、图片动态渲染到 word 中,最终生成 pdf 文件。


     技术调研3 种方案,从简单到复杂

         1. word模版直接给前端,让前端写成 html,php 实现 html 模版动态填充内容,调用插件方法转 pdf

         2. php 实现 word内容填充,服务器安装 LibreOffice 服务,由 LibreOffice 去实现 word 转 pdf,省去转 html 模版

        3. php 实现  word 内容填充-> 转html -> 转pdf,这篇文章实现该方案。不麻烦前端、服务器运维人员。真是懒得去沟通了。累。哈哈!!


     注:最终生成的 pdf 中文乱码,请看到文章最后。


四、转换过程

      word -> html -> pdf,1-2页 word 秒级在服务器转成 pdf


五、word模版示例:

image.png


六、代码示例

// 引入命名空间,对应操作类。
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\TemplateProcessor;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\Writer\Html;
use Dompdf\Dompdf;
// 以下代码放在类或者方法中。
//--------------------------- 示例代码 ----------------------------
// 实例化 PhpWord 类
$phpWord = new PhpWord();
// word 中全局默认文字
$phpWord->setDefaultFontName('宋体');
$phpWord->setDefaultFontSize(12);
//--------------------------- 1. 填充文字、图片到 word 中 START ----------------------------
// 如果生成多个PDF,将以下代码,包裹在循环中
// 参数是 word 模版绝对路径
$oTemplateProcessor = new TemplateProcessor(public_path('uploads/word_template.docx'));
// 替换 word 中对应的变量
$oTemplateProcessor->setValue('name', '姓名');
$oTemplateProcessor->setValue('text1', '同意我司各种公平的协议,很多很多文字');
$oTemplateProcessor->setValue('text2', '感谢您的信任与支持,很多很多文字');
$oTemplateProcessor->setValue('unit', '单位');
$oTemplateProcessor->setValue('id_num', '11010120250211010101010101');
$oTemplateProcessor->setValue('mobile', '13888888888');
// 图片,先确认文件存在
$imgFile = public_path('uploads/xxx.png');
if (file_exists($imgFile)) {
      // 这里可以设置宽度、高度
      $img = ['path' => $imgFile, 'width' => 800, 'height' => 300];
      $oTemplateProcessor->setImageValue('sign_img', $img);
} else { // 图片如果不存在,将word对应的值,置空
     $oTemplateProcessor->setValue('sign_img', '');
}
// 保存 word 文件
$wordPath = public_path('uploads/word.docx');
$oTemplateProcessor->saveAs($wordPath);
//--------------------------- 1. 填充文字、图片到 word 中 END ----------------------------
//--------------------------- 2. word 转 HTML START----------------------------
// 加载 Word 文件
$phpWord = IOFactory::load($wordPath);
// 将 Word 转换为 HTML
$htmlWriter = new Html($phpWord);
ob_start();
$htmlWriter->save('php://output');
$htmlContent = ob_get_clean();
// 调试:将 HTML 内容保存到文件
$file =  'html.html';
$htmlPath = public_path('uploads/html/' . $file);
file_put_contents($htmlPath, $htmlContent);


// 下面这3行是防止生成 PDF 乱码,替换了 html 中的字体,word-break:break-all; word-wrap:break-word;这个是为了中文多行的文本换行。 '800px', '300px'是图片的宽高。请根据自己实际业务进行调整。
$htmlContent = file_get_contents($htmlPath);
$res = str_replace(['Times New Roman', '宋体', 'font-family: \'simsun\'; font-size: 12pt;', '800px', '300px'], ['simsun, DejaVu Sans, sans-serif', 'simsun', 'font-family: \'simsun\'; font-size: 12pt;word-break:break-all; word-wrap:break-word;', '600px', '225px'], $htmlContent);
file_put_contents($htmlPath, $res);


//--------------------------- 2. word 转 HTML END ----------------------------
//--------------------------- 3. html 转 PDF START ----------------------------
// 创建一个Dompdf实例
$dompdf = new Dompdf();
// 将HTML内容加载到Dompdf中
$dompdf->loadHtml(file_get_contents($htmlPath));
// (可选)设置PDF的页面尺寸和方向
$dompdf->setPaper('A4', 'portrait');
// 渲染HTML内容dompdf->render();
$dompdf->render();
// 将生成的PDF文件保存到服务器上
$pdfPath = public_path('uploads/pdf/') . 'pdf.pdf';
file_put_contents($pdfPath, $dompdf->output());
//--------------------------- 3. html 转 PDF END ----------------------------


七、PDF 中文乱码

  1. 检查 word 使用的字体,例如我使用的宋体

  2. 检查 HTML 中,中文显示是否正常

  3. 解决 PDF 乱码:

    1. 从 https://github.com/dompdf/utils 仓库下载 load_font.php 文件

    2. 下载字体文件,格式 xxx.ttf,我使用的是宋体,文件名为:simsun.ttf

    3. 将 load_font.php 和 xxx.ttf 字体文件,这2个文件放在[项目根目录],不是public下面,是和public平级

      image.png

    4. 使用命令行切换到项目目录下执行

       php load_font.php simsun simsun.ttf

    网上搜的图,当时自己执行后的早忘了。。成功后的示意:

    image.png

     e. 重新执行代码生成在试下

     f.  啰嗦一下,如果生成 PDF 格式不太对,就看看改改 HTML 中 CSS,不断的调试。 

       g. 生成没问题后,注意的点是代码部署到测试、生产环境之后, php load_font.php simsun simsun.ttf 这个命令是需要执行的,我的场景是每次部署后会自动执行这行命令。否则在服务器上生成的 PDF 还是乱码。