dompdf中文乱码、换行解决方案
dompdf中文乱码、换行解决方案
文章目录
- 前言
- 使用环境
- 安装dompdf
- 使用dompdf
- 中文乱码问题
- 中文换行问题
- 页面设置问题
- PDF生成问题
- 自定义注入变量方法
- 结语
前言
因为工作需要,需要使用PHP生成PDF,开始接触dompdf这个类库,dompdf可以把HTML文件生成PDF。
无奈使用的过程中遇到很多坑,细数dompdf的一些坑,中文乱码,中文换行,页面设置问题,生成文档,无奈还是使用,只能硬着头皮去找解决方案,网上许多方法只讲了一部分,没有发现一个好完整的解决方案,大多是随意复制粘贴,或者答非所问。
最后自己东拼西凑,终于整理出完整的解决方案,今天就记录下这些坑的解决方案,以免以后又踩坑,不废话直接进入正题。
使用环境
0、版本不同,可能会导致解决方案行不通,故记录使用环境。
1、Apache/2.4.33 (Win64) PHP/5.6.35
2、ThinkPHP5.0.21
3、dompdf v0.8.2
安装dompdf
1、使用命令行进入到项目根目录
cd C:\wamp64\www\tp5
2、使用composer安装dompdf
composer require dompdf/dompdf
3、检查是否安装成功,在C:\wamp64\www\tp5\vendor看是否有dompdf文件夹。
使用dompdf
0、因为dompdf有许多中文的坑,刚开始最好不要使用中文测试,免得心情糟糕。
1、引入Dompdf
use Dompdf\Dompdf;
2、获得HTML内容、相对于项目入口的目录
$html = file_get_contents('templates/1.html');
3、加载html
$dompdf->loadHtml($html);
4、设置页面属性 A4的纸张,
$dompdf->setPaper('A4', 'portrait');
5、渲染PDF
$dompdf->render();
6、在浏览器中下载,这行代码会自动在浏览器中下载
$dompdf->stream();
中文乱码问题
0、重点来了,相信这个问题不解决,大家也不会再考虑使用这个类库,一堆乱码看着简直心情糟糕透了。
1、下载类库语言安装脚本
https://github.com/dompdf/utils.git
2、将里面的load_font.php文件拷贝到项目根目录,和verdor同级
目录:C:\wamp64\www\tp5
3、下载一个宋体字体 simsun.ttf,也放到项目根目录,这时load_font.php和simsun.ttf应该在同一级目录
目录:C:\wamp64\www\tp5
4、开始安装字体,使用命令行进入当前目录,并安装字体
cd C:\wamp64\www\tp5php load_font.php simsun.ttf simsun
命令说明 php load_font.php 调用这个文件,并传入字体路径,字体名字
注意这一步,最后的simsun最好不要添加引号,看有一些例子写了引号,导致后面声明字体使用不上。
5、安装结果图,显示这些东西基本就完成字体安装。
6、去类库字体目录检查是否安装成功
C:\wamp64\www\tp5\vendor\dompdf\dompdf\lib\fonts
找到是否有simsun.ttf和simsun.ufm2个文件
7、一般来说到上一步就安装成功,不放心可以进行终极检查
进入到这个目录:C:\wamp64\www\tp5\vendor\dompdf\dompdf\lib\fonts
找到这个文件:dompdf_font_family_cache.php
看下是否有以下这段,没有就添加上,有就最好。
'simsun' => array('normal' => $fontDir . '/simsun','bold' => $fontDir . '/simsun','italic' => $fontDir . '/simsun','bold_italic' => $fontDir . '/simsun',)
8、在HTML中使用我们安装的字体,你可以在这个HTML任何地方写这个字体样式,不过为了全文显示正常最好还是在这写。
<body style="font-family:simsun">中文字体</body>
这样我们就可以愉快的使用中文字体了。
中文换行问题
0、当我开心解决了中文乱码问题之后,又发现了换行问题,中文不会换行,在网上找到寻找到了解决方案不过有点出入,版本不一样的问题。
1、寻找到Text.php文件
我的目录:C:\wamp64\www\tp5\vendor\dompdf\dompdf\src\FrameReflower\Text.php
2、找到相关代码
// split the text into words$words = preg_split('/([\s-]+)/u', $text, -1, PREG_SPLIT_DELIM_CAPTURE);$wc = count($words);
3、替换以上代码,或者注释掉以上代码,添加我们的代码。
preg_match_all("/./u", $text, $array);$words = array(0);$wc = count($words);
4、小提示,可能因为版本的变迁,文件、代码位置不一样,大家最好使用目录全文搜索那一段代码,而不是直接去找那个文件。
页面设置问题
0、不知道什么原因,网上大多的例子都是横向设置,我还纠结半天什么鬼,内容在一个页面显示不了分了好几页,只能说英文不好容易踩坑。
1、设置页面
//网上你可能看到很多这样的例子,我要竖着的看啊,坑。$dompdf->setPaper('A4', 'landscape');//找了类库说明,发现还有一个参数,这下终于可以正常显示了。$dompdf->setPaper('A4', 'portrait');
2、为了更好将HTML转换成PDF,建议将HTML宽高设置成和A4大小接近,避免不必要的麻烦。个人还是要根据实际pdf显示情况来调节。
body {margin: 0;width: 820px;height: 1160px;}
PDF生成问题
0、又解决了一个问题,这下真的万事大吉了嘛,nono,dompdf目前还是存在样式问题,没有得到很好的解决,所以这点需要的注意。
1、对元素浮动支持不是很友好。float
2、目前不支持css3的属性,所以不要奢望做出很复杂的样式。
自定义注入变量方法
0、为什么要注入变量,直接使用TP5里的注入方法不就可以了?我们是直接读取模板文件,而不通过页面渲染出来,所以我自己写个方法,用来向HTML中注入一些变量。有很多方法可以实现,有兴趣大家慢慢探索。
1、批量生成pdf如果需要头尾模板分离的话,可以使用HTML拼接的方式。
$html = file_get_contents('public/letters/templates/html/header.html');$html .= file_get_contents($path);$html .= file_get_contents('public/letters/templates/html/footer.html');
2、HTML模板按照以下方式写要替换的变量,代表要替换的变量。
{test}
3、变量注入方法,将模板和所有的变量传入这个方法,返回一个新的模板。
/*** 轻量级变量注入方法、可以自行完善*/public function inject($html,$common){//匹配模式$pattern = '/\{([\w]+)\}/';//捕获所有的模板变量preg_match_all($pattern,$html,$matches);//变量替换for($i=0;$i<count($matches[1]);$i++){if(isset($common[$matches[1][$i]])){$html = preg_replace('/\{'.$matches[1][$i].'\}/',$common[$matches[1][$i]],$html);}}return $html;}
4、完整例子代码:
//模板路径$path = 'public/templates/1.html';//文件生成路径$filePath='public/pdf/test.pdf';//声明一个DomPDF对象$dompdf = new Dompdf();//HTML组合$html = file_get_contents('public/templates/html/header.html');//中间需要替换的部分$html .= file_get_contents($path);$html .= file_get_contents('public/templates/html/footer.html');//注入的变量$data['test'] = 'test';//HTML注入变量$html = $this->inject($html,$data);//加载HTML内容$dompdf->loadHtml($html);//设置PDF纸张、方向 portrait、landscape$dompdf->setPaper('A4', 'portrait');// 渲染pdf$dompdf->render();//生成一个pdf文件file_put_contents($filePath,$dompdf->output());
结语
以上是我最近折腾dompdf的完整经历,从一个问题到一个问题,还好最终都一一解决了。
很多问题也不能只靠网上百度,也要学会自己思考,阅读源代码结合自己一些编程经验找到解决方案。
这也是本人第一篇比较长分享文章了,希望能帮助同样使用这个类库的人。