TP6将HTML转换为PDF文件,非法UTF-8编码和中文乱码问题

目录

1、前言

2、使用环境

3、安装dompdf

4、使用dompdf

5、中文乱码问题

6、页面设置问题

7、PDF生成问题

8、模板变量读取

结语


1、前言

最近搞生成合同模板功能时,需要使用PHP生成PDF,开始接触dompdf这个类库,dompdf可以把HTML文件生成PDF。

遇到一些问题,参考了一些网上的解决方法,特汇总备用。

2、使用环境

版本不同,可能会导致解决方案行不通,故记录使用环境。

1、Nginx1.15 (Win64) PHP/7.4.3

2、ThinkPHP6.1

3、dompdf v2.0.8

3、安装dompdf

1、使用命令行进入到项目根目录;

2、使用composer安装dompdf;

php 复制代码
composer require dompdf/dompdf

3、检查是否安装成功,在vendor 中查看是否有dompdf文件夹。

4、使用dompdf

4.1)在common.php文件中构建html_to_pdf函数

php 复制代码
// 文件路径:common.php

use Dompdf\Dompdf;
use Dompdf\Options;

if (!function_exists('html_to_pdf')) {
    function html_to_pdf($html, $filename = 'document.pdf', $stream = true) {
        $options = new Options();
        //设置使用远程图片填充pdf内容
        $options->set('isRemoteEnabled', true);
        //$options->setIsRemoteEnabled(true);

        //设置html文件编码
        $html = mb_convert_encoding($html, 'UTF-8');

        $dompdf = new Dompdf($options);
        $dompdf->loadHtml($html);

        //设置纸张大小和方向
        $dompdf->setPaper('A4', 'portrait');
        $dompdf->render();

        if ($stream) {
            //直接在浏览器下载生成的pdf文件
            $dompdf->stream($filename, ['Attachment' => 0]);
        } else {
            //将生成的pdf保存到服务器
            file_put_contents($filename,$dompdf->output());
            return $dompdf->output();
        }
    }
}

4.2) 在项目中调用html_to_pdf函数生成pdf文件

php 复制代码
$template_content = '<html lang=\"en\">'.
            '<head>'.
                '<meta charset=\"UTF-8\">'.
                '<title>这是pdf</title>'.
                '<link rel="stylesheet" href="http://www.pdf.com/static/css/admin/main.css">'.
            '</head>'.
            '<body>'.
                '<div>'.
                    '<p class="p01">我是html文件哈:{$name}----{$email}</p>'.
                    '<p style="color: #ff4036; font-size: 30px; font-weight: bold;text-align: center;">标题一:----{$name}</p>'.
                    '<p>标题二:----{$email}<br/><br/> 我换行啦,我是用来测试<br/>中文换行的啦,请换行看结果,不支持中文换行</p>'.
                    '<p>标题三:----{$email}</p>'.
                '</div>'.
            '</body>'.
            '</html>';

$html =  View::display($template_content, ['name' => '这是变量名字啦', 'email' => 'pdf@qq.com']);

html_to_pdf($html, 'template01.pdf', false);//生成pdf文件,不显示、不直接下载

备注:

view模板变量的调用这里不再赘述,大家看tp文档即可。
ThinkPHP官方手册

5、中文乱码问题

错误1

php 复制代码
{"code":0,"msg":"Malformed UTF-8 characters, possibly incorrectly encoded","data":{"code":0,"line":50,"file":"D:\\myweb\\ytems\\vendor\\topthink\\framework\\src\\think\\response\\Json.php","message":"Malformed UTF-8 characters, possibly incorrectly encoded","trace":[{"file":"D:\\myweb\\ytems\\vendor\\topthink\\framework\\src\\think\\Response.php","line":388,"function":"output","class":"think\\response\\Json","type":"->","args":[false]},{"file":"D:\\myweb\\ytems\\vendor\\topthink\\framework\\src\\think\\Response.php","line":131,"function":"getContent","class":"think\\Response","type":"->","args":[]},{"file":"D:\\myweb\\ytems\\public\\index.php","line":22,"function":"send","class":"think\\Response","type":"->","args":[]}]}}

原因

当出现以上错误时,可能是html文件编码问题(网上查找答案时大多给出的是这个处理方法),然后我用网上提供的方式修改html编码后依旧无法解决这个问题,后来排查发现,竟然是因为我在已经打开的生成pdf文件的基础上再次执行代码重复生成同名的pdf文件导致,关闭打开的pdf文件,再次执行代码,问题解决。

错误2

生成pdf文件中文乱码问题。

解决:

1、下载类库语言安装脚本

https://github.com/dompdf/utils.git

2、将里面的load_font.php文件拷贝到项目根目录,和vendor同级

php 复制代码
PS D:\myweb\ytems>

3、下载宋体字体文件 simsun.ttf 也放置在项目根目录,如上ytems目录,也与vendor同级,与load_font.php同目录。

simsun字体下载|simsunttcsimsunttf字体包v6.457袖珍官方-雨林木风系统

4、开始安装字体,使用命令行进入根目录(即刚刚存储load_font.php文件 和 simsun.ttf文件的ytems目录),并安装字体。

php 复制代码
php load_font.php simsun simsun.ttf

命令说明: php load_font.php 字体路径,字体名字

注意,simsun simsun.ttf 两个参数不可以写反成:simsun.ttf simsun

否则会报以下错误:

php 复制代码
PS D:\myweb\ytems> php load_font.php simsun.ttf simsun
PHP Fatal error:  Uncaught Dompdf\Exception: Unable to read 'simsun'. in D:\myweb\ytems\load_font.php:86
Stack trace:
#0 D:\myweb\ytems\load_font.php(201): install_font_family(Object(Dompdf\Dompdf), 'simsun.ttf', 'simsun')
#1 {main}
  thrown in D:\myweb\ytems\load_font.php on line 86

5、安装结果图,显示这些东西基本就完成字体安装。

php 复制代码
PS D:\myweb\ytems> php load_font.php simsun simsun.ttf
Unable to find bold face file.
Unable to find italic face file.
Unable to find bold_italic face file.
Copying simsun.ttf to D:\myweb\ytems\vendor\dompdf\dompdf/lib/fonts/simsun.ttf...
Generating Adobe Font Metrics for D:\myweb\ytems\vendor\dompdf\dompdf/lib/fonts/simsun...

6、去类库字体目录检查是否安装成功

vendor\dompdf\dompdf\lib\fonts

找到是否有simsun.ttf和simsun.ufm2个文件,存在即安装成功

7、修改路径 vendor\dompdf\dompdf\lib\fonts 下的字体配置文件 installed-fonts.json文件中字体的本地存储路径为相对路径,防止直接上传vendor到线上时出错。

html 复制代码
      'simsun' => array(
        'normal' =>  'simsun',
        'bold' =>  'simsun',
        'italic' => 'simsun',
        'bold_italic' =>  'simsun',
      )

8、在HTML中使用我们安装的字体,你可以在这个HTML任何地方写这个字体样式,不过为了全文显示正常最好还是在这写。

html 复制代码
    <body style="font-family:simsun">中文字体</body>

这样我们就可以愉快的使用中文字体了。

6、页面设置问题

不知道什么原因,网上大多的例子都是横向设置,我还纠结半天什么鬼,内容在一个页面显示不了分了好几页,只能说英文不好容易踩坑。

1、设置页面

//网上你可能看到很多这样的例子,我要竖着的看啊

php 复制代码
      $dompdf->setPaper('A4', 'landscape');//横向设置

//找了类库说明,发现还有一个参数,这下终于可以正常显示了。

php 复制代码
      $dompdf->setPaper('A4', 'portrait');

2、为了更好将HTML转换成PDF,建议将HTML宽高设置成和A4大小接近,避免不必要的麻烦。个人还是要根据实际pdf显示情况来调节。

html 复制代码
body {
    font-family:simsun;
    margin: 0;
    width: 800px;
    height: 1160px;
}

7、PDF生成问题

dompdf目前还存在样式问题,没有得到很好的解决,所以需要注意以下两点:

1、对元素浮动支持不是很友好。如 float

2、目前不支持css3的属性,所以不要奢望做出很复杂的样式。

8、模板变量读取

结语

以上为整理的dompdf的完整使用过程,留存备用。

参考链接:

dompdf中文乱码、换行解决方案_dompdf 中文乱码-CSDN博客

相关推荐
开心工作室_kaic7 分钟前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā7 分钟前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年1 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder2 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727572 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart2 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter
会发光的猪。2 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客3 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记3 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
前端李易安3 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js