原理
原始数据->加载模板->临时文件->PDF文件
方案准备
- html模板转pdf 难点:1. 每次变化都要找设计师;2. html样式很难控制(个人不擅长);3.html转pdf样式难以控制
- word模板转pdf 难点:1. 合适插件的选择;2. 中文的处理
最终选择,word模板模式
实现步骤
- WORD插件 开源地址
composer require phpoffice/phpword
phpword非常好用,支持变量,太方便了。
- WORD转PDF插件 下载地址
/opt/libreoffice6.4/program/soffice
- 完整demo
//生成订单pdf
public function order_pdf_f()
{
#1. 准备订单信息
$person_addr = "北京市";
$person_name = "张三";
$person_mobile= "18932000000";
#2. 生成素材文件
$res_dir_path = './res/';
$templateFile = $res_dir_path.'temp_order.docx';
$wordPath = $res_dir_path.'tmp/hello.docx';//计算机上的一个文件
try {
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($templateFile);
$templateProcessor->setValue('person_name', $person_name);
$templateProcessor->setValue('person_addr', $person_addr);
$templateProcessor->setValue('person_mobile', $person_mobile);
$templateProcessor->saveAs($wordPath);
} catch (Exception $e) {
echo $e->getMessage();
return;
}
#3. 生成pdf并下载
try {
$pdfPath = $res_dir_path.'tmp';
$set_charset = 'export LANG=zh_CN.UTF-8;';#linux
$cmd = $set_charset."\n"."/opt/libreoffice6.4/program/soffice --headless --convert-to pdf:writer_pdf_Export {$wordPath} --outdir {$pdfPath}";
$status = 1;
$log = null;
$log = shell_exec($cmd);
if(is_null($log)) {
#echo "start exec";
exec($cmd.' 2>&1', $log, $status);
}
sleep(1);
#4. 页面跳转到下载
$file =$pdfPath."/hello.pdf";//计算机上的一个文件
$fileName = basename($file);//获取文件名
header("Content-Type:application/octet-stream"); //告诉浏览器文档类型(mime类型); octet-stream指的是二进制文件类型;下载任何类型的文件都可以这么指定
header("Content-Disposition:attachment;filename=".$fileName); //告诉浏览器以附件方式对待文件(即下载文件);并设置下载后的文件名
header("Accept-ranges:bytes"); //告诉浏览器文件大小的单位
header("Accept-Length:".filesize($file)); //告诉浏览器文件的大小
$h = fopen($file, 'r'); //打开文件
echo fread($h, filesize($file));
} catch (Exception $e) {
echo $e->getMessage();
return;
}
}
注意
导出时,老是出现乱码,一开始比较抓狂。不知道哪里出了问题。后来冷静分析了一下。
- 数据->word模板->word文件,只要生成的word文件,没有乱码就成功一半了 系统环境变量修改
#1. 修改语言环境变量
vi /etc/locale.conf
LANG=zh_CN.UTF-8
插件底层源码修改
/www/wwwroot/项目名/vendor/phpoffice/phpword/src/PhpWord/TemplateProcessor.php
第256行
/**
* @param string $subject
*
* @return string
*/
protected static function ensureUtf8Encoded($subject)
{
if (!Text::isUTF8($subject)) {
#$subject = utf8_encode($subject);
$subject = iconv("GB2312","UTF-8//IGNORE",$subject);
}
return $subject;
}
- word文件->pdf,要是还有乱码,考虑是字体的原因。安装字体解决 https://blog.csdn.net/wlwlwlwl015/article/details/51482065
#1. 在CentOS 4.x开始用fontconfig来安装字体库
yum -y install fontconfig
#2. 创建中文字体路径
mkdir -p /usr/shared/fonts/chinese
#3. ftp上传字体到 /usr/shared/fonts/chinese
c盘下的Windows/Fonts目录
#4. 修改字体权限
chmod -R 755 /usr/share/fonts/chinese
#5. 安装ttmkfdir来搜索目录中所有的字体信息
yum -y install ttmkfdir
#6. 执行ttmkfdir命令
ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir
#7. 引入中文
vi /etc/fonts/fonts.conf
...
<dir prefix="xdg">fonts</dir>
<dir>/usr/share/fonts/chinese</dir> #新加这行
...
#8. 刷新内存中的字体缓存
fc-cache
#9. 检查是否生效
fc-list
来源:oschina
链接:https://my.oschina.net/u/2351685/blog/3288678