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
  • 总共6条评论
白俊遥博客

夜華:可以来个示例吗?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 回复

白俊遥博客 白俊遥博客
  • 云淡风晴 回复 Tina:可以;不过现在网上的教程挺多的;可以先搜着看;
  • 2018-03-31 19:30:31 回复
白俊遥博客

null:这个略微有些高深啊

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

白俊遥博客 白俊遥博客
  • 云淡风晴 回复 null:就是安装麻烦;
  • 2018-03-31 19:30:45 回复
白俊遥博客
  • echo "hello"; 回复 null:请先登录后回复评论
  • 2018-04-06 15:56:52 回复