php编辑word内容通过unoconv调用LibreOffice输出pdf打印

关于我把 word 和 pdf 来回整的故事;
我有一段血泪史;
惊天地;泣鬼神;痛彻心扉;穿越前世今生;
今天我准备熬夜把它控诉一遍;

之前有一些愚蠢的人类给了伟大的程序猿一份 word 文档;
里面就一段文字;
需求是能动态的替换其中的部分内容;
然后转成 pdf 供用户下载;

这简单啊;
还要啥 word 文档啊;
直接手动把内容复制出来;
放好占位符用 php 的字符串替换函数动态替换下;
然后使用 tcpdf ;
生成 pdf so easy ;
根本不用点读机;
我写过文章可以参考thinkphp整合系列之tcpdf类生成pdf文件

然鹅需求如某某;
她总是善变的;
希望能有点样式加点图片;
说起样式图片我们都知道前端是擅长的;
我们可以先用 HTML+CSS 排好版了;
整个页面作为一个字符串替换其中的占位符即可;
然后用 dompdf 把 HTML 转成 PDF;
虽然曲折麻烦了点;
但是实现起来也不算难;

可万万没想到;
她不但善变还需求不满;
希望有页眉页脚页数
图片样式间隔;
而且一搞就来10几页的 word 文档;
而且还要经常换各种花样;
而且要生成的 pdf 要跟 word 源文档要保持一致到像素级别;
显然想像之前那样纯依赖 php 就完成是有点吃力了;
那么下面就有请 LibreOffice 上场了;
现在我们开始正文;
思路是这样的;
我们用 php 来编辑替换 word 文档内容;
然后调用 LibreOffice 把 word 替换成 pdf 文档;

用 php 编辑替换 word 就比较简单了;
扩展包在这PHPWord
文档很容易使用;
这里简单写两句;
在 word 源文件中占位符要包裹在 ${} 中;
比如说在 source.docx 中是这样的;

${name}博客666

php 调用 setValue 方法第一个参数传 name 第二个参数传值就可以替换了;

 use PhpOffice\PhpWord\TemplateProcessor;

        $phpWord = new TemplateProcessor('source.docx');
        $phpWord->setValue('name', '白俊遥');
        $phpWord->saveAs('new.docx');

new.docx 文件中就被替换成 白俊遥博客666了;

重点要来了;
LibreOffice 折腾起来就稍微麻烦且有坑了;
先下载软件和语言包;

cd /usr/local
wget https://downloadarchive.documentfoundation.org/libreoffice/old/5.2.7.2/rpm/x86_64/LibreOffice_5.2.7.2_Linux_x86-64_rpm.tar.gz
wget https://downloadarchive.documentfoundation.org/libreoffice/old/5.2.7.2/rpm/x86_64/LibreOffice_5.2.7.2_Linux_x86-64_rpm_langpack_zh-CN.tar.gz
wget https://downloadarchive.documentfoundation.org/libreoffice/old/5.2.7.2/rpm/x86_64/LibreOffice_5.2.7.2_Linux_x86-64_rpm_helppack_zh-CN.tar.gz

如果用 wget 速度几k到几十k不等/s 的话;
那推荐用迅雷下载到本地;在传到服务器的 /usr/local 目录;
把下载的这几个文件批量解压了;

ls LibreOffice_5.2.7_Linux_x86-64_rpm* | xargs -n1 tar -zxvf

依次安装;

sudo yum -y install ./LibreOffice_5.2.7.2_Linux_x86-64_rpm/RPMS/*.rpm
sudo yum -y install ./LibreOffice_5.2.7.2_Linux_x86-64_rpm_langpack_zh-CN/RPMS/*.rpm
sudo yum -y install ./LibreOffice_5.2.7.2_Linux_x86-64_rpm_helppack_zh-CN/RPMS/*.rpm

安装成功后到 /opt/libreoffice5.2 目录下载 unoconv;
这是一个用来方便调用命令把 word 转成 pdf 的工具;

cd /opt/libreoffice5.2
wget https://raw.githubusercontent.com/dagwieers/unoconv/master/unoconv

给予权限并链接;

chmod +x unoconv
sudo ln -s /opt/libreoffice5.2/unoconv /usr/bin/unoconv

这个时候虽然说已经可以转换了;
但是中文是会乱码的;
创建字体文件目录;

mkdir /usr/share/fonts/Windows

然后把 C:\Windows\Fonts 中的所有字体上传到 /usr/share/fonts/Windows
给予权限并刷新;

sudo chmod -R 755 /usr/share/fonts/Windows
sudo fc-cache -fv

再来个转换的函数;

if (! function_exists('word_to_pdf')){
    /**
     * 把word转pdf
     *
     * @param $wordPath
     * @param $pdfPath
     * @return string
     */
    function word_to_pdf($wordPath, $pdfPath)
    {
        set_time_limit(0);
        putenv('HOME=/home/apache/');
        // 生成pdf文件
        shell_exec('/usr/bin/unoconv -f pdf -o ' . $pdfPath . ' ' . $wordPath);
    }
}

最后需要注意的是如果是使用的是 nginx ;
php-fpm 的 user 不要是 nobody;
一般是 nginx 或者 www;
如果没有如期生成 pdf 文件;
使用 su nginx 或者 su www 后要手动执行 shell_exec 中的命令;
根据错误提示解决;

白俊遥博客
请先登录后发表评论
  • latest comments
  • 总共11条评论
白俊遥博客

SV :刚看到这篇文章,血亏,早点看到就可以拿去直接用了!!!   这个需求,我前段时间也有几乎一模一样的需求,我是用python的docxtpl库 做word替换,然后也是用libreoffice转pdf

2021-01-31 05:48:33 回复

白俊遥博客

夜華 :可以来个示例吗?linux方面没啥问题,反而是word处理这边有点....

2019-09-24 11:08:42 回复

白俊遥博客

无法埋名 :请问php执行shell_exec 需要设置什么地方吗?我之前做那个视频格式转m3u8,用的ffmepg组件,exec或者system函数执行失败,但是在终端执行可以转换成功

2019-01-26 18:52:01 回复

白俊遥博客

古红平 :我之前遇到过,感觉像是路径问题,如果你在php里拼好执行的全路径,应该是可以的。

2019-06-19 09:27:01 回复

白俊遥博客

花舞千魂殇 :然鹅需求如某某;她总是善变的;哈哈 我笑了

2018-08-29 17:12:35 回复

白俊遥博客

:去

2018-03-29 19:08:07 回复

白俊遥博客

Tina :大神能不能出一个网站http转https的详细教程,感觉这个很实用喔白俊遥博客

2018-03-29 16:50:23 回复

白俊遥博客 白俊遥博客

云淡风晴 :可以;不过现在网上的教程挺多的;可以先搜着看;

2018-03-31 19:30:31 回复

白俊遥博客

null :这个略微有些高深啊

2018-03-27 13:32:22 回复

白俊遥博客 白俊遥博客

云淡风晴 :就是安装麻烦;

2018-03-31 19:30:45 回复

白俊遥博客

echo "hello"; :请先登录后回复评论

2018-04-06 15:56:52 回复