word转html方法调研

最近有需求可能用到word转html,所以前期调研了一番,整理如下。

问题描述

在不明确问题的情况下谈解决方案是不明智的,所以先明确问题:

现在线下有一批word文档,后台提供上传入口,上传后需要将内容解析出来并支持在富文本编辑器中编辑,word文档内有留白,可以在编辑器内填上内容,生成新的数据,原word与新生成的word最终都要已pdf的形式留存。

我是这样分析的:

第一种方案

  1. word上传后需要能在编辑器内编辑,所以需要word转html。

  2. 最终的word需要生成为pdf,也就要求第一步生成的html能保证格式的情况下生成pdf。

第二种方案

早在之前就了解过word生成pdf,所以自然想到能否不通过html,直接word到pdf呢?这样不但可以减少代码的复杂度,也能减少误差,毕竟机器的转换次数越多,误差就越大。

但是根据问题的描述,导入的word其实就是类似于模板,我们需要能编辑,但是这个方法,可能不太方做内容的调整,所以这种方法待定。

word to html

所有方法只讲具体实现,详情可查看官网。

1. unoconv

unoconv这个工具是依赖于LibreOffice或OpenOffice,这两个Office都是基于开源软件的,通常用LibreOffice(可能因为是协议的原因,LibreOffice功能更全面),包括Debian等发行版默认也安装的LibreOffice。

安装LibreOffice最新版

我的是Centos环境,下载的rpm包,解压后使用如下命令安装:

1
2
cd dir
yum -y install ./*.rpm

这里没有用rpm -ivh ./*.rpm是因为rpm命令不能解决依赖问题,yum可以帮我们解决。

安装unoconv

官网最下面有链接,直接下载解压,目录里有unoconv命令,直接执行即可。

问题处理:

  1. 执行unoconv命令后:
1
/opt/libreoffice6.2/program/python.bin: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by /opt/libreoffice6.2/program/libpython3.5m.so.1.0)

看来是LibreOffice依赖于更高版本的glibc,注:glibc是整个系统的基础,轻易不要动。因为我这边是docker环境,而且有备份,所以还是简单的尝试了下:

查看当前glibc版本:

1
strings /lib64/libc.so.6 | grep GLIBC_

看下yum源里面的版本:

1
rpm -qa | grep glibc

没有GLIBC_2.14版本,在这个链接下载,下载下来通过这些步骤进行安装(没有备份,谨慎操作):

1
2
3
4
5
6
cd dir
make build && cd build
../configure --prefix=/usr/local/glibc-2.14
make -j4
sudo make install
export LD_LIBRARY_PATH=/usr/local/glibc-2.14/lib:$LD_LIBRARY_PATH

注:这些步骤我没有完全执行完,因为这个安装非常慢。

glibc不好升级,那就把LibreOffice降级,我的系统glibc的最高版本是2.12,所以重新下载了5.4.7,这个没找到官方提供的说明,完全是凭感觉。

安装完成后,启动office服务,不启动也可以的,基于c/s架构的性能会好一些。

1
2
cd dir
./soffice --nologo --headless --accept="socket,host=127.0.0.1,port=8100;urp;StarOffice.ServiceManager" &

启动之后可能会有如下几个问题:

1
/opt/libreoffice5.4/program/soffice.bin: error while loading shared libraries: libcairo.so.2: cannot open shared object file: No such file or directory

解决方案:

1
yum install ibus

此时我的思路有点懵逼,看了下yum源有没有这个软件(4.3.7版本),然后就安装了。。。。后来索性有把之前安装的版本卸载了。

之后用启动命令,碰到的几个问题,对应的解决方案:

  1. 问题
    1
    2
    javaldx: Could not find a Java Runtime Environment!
    Warning: failed to read path from javaldx

解决方案:

1
yum -y install libreoffice-base
  1. 问题
    1
    /usr/lib64/libreoffice/program/soffice.bin X11 error: Can't open display

解决方案:

1
yum install libreoffice-headless

  1. pdf乱码,后来想直接转换为pdf用来着,此时我已经焦虑了,看下面的命令就知道,哈哈。
    1
    2
    yum -y install libreoffice*
    yum groupinstall chinese-support

到目前为止,可能碰到的问题都解决了,还是进行转换:

1
2
cd dir
./unoconv --connection "socket,host=127.0.0.1,port=8100;urp;StarOffice.ComponentContext" -f html -o a.html a.docx

生成了html,迫不及待看一眼什么样,样式基本都在,但是源文件是在太乱了,放在富文本编辑器内表现还可以,但是通过tcpdf生成的pdf基本就没法看了。至于为什么用tcpdf来生成pdf,首先是因为项目当前用的就是tcpdf,切换有一定的成本,二来就是我们不能为了解决这个问题容忍凌乱的html代码,无论从数据存储还是后期维护,都不能这样做。

自动生成的代码不行,就按文本进行干净化处理,但是考虑到源word文档的多样性,可能会出现各种小问题,所以这样方案也pass掉了。

2. pandoc

中文文档

安装:

1
yum -y install pandoc

执行命令转换:

1
pandoc zz.docx -o a.html

报错:

1
pandoc: zz.docx: hGetContents: invalid argument (invalid UTF-8 byte sequence)

这个问题没有解决,可能是版本的问题,又尝试下载了最新版本,在这,解压后的bin目录下的命令可以直接执行,结果正常。

在mac下也安装试了下:

安装:

1
2
brew install pandoc
brew install pandoc-citeproc

同样执行上面的转换命令,结果一致。

也可以执行这个命令,可以添加自定义的头:

1
pandoc -s zz.docx -o a.html

出现如下错误:

1
2
3
4
[WARNING] This document format requires a nonempty <title> element.
Please specify either 'title' or 'pagetitle' in the metadata,
e.g. by using --metadata pagetitle="..." on the command line.
Falling back to 'zz'

根据提示应该是需要补充个标题,用下面这个命令解决:

1
pandoc -s zz.docx --metadata title:"title" -o a.html

成功了,同样还是迫不及待,输出结果代码相比unoconv,代码少了很多,代价就是丢失了些样式,比如字体大小,左右对其这种基本的页没有了,总体来说仍然不能使用。

3. phpword

试了以上两种命令式的方法,均不能解决问题,所以尝试下直接用php扩展来处理。

phpword默认使用composer来安装,但是我们项目没有使用composer环境,可以到这个链接下载完整的require文件包,直接在项目引用即可。

如下php代码:

1
2
3
4
require_once APP_PATH . '/classes/PHPWord/vendor/autoload.php';
$phpWord = \PhpOffice\PhpWord\IOFactory::load('a.docx');
$xmlWriter = \PhpOffice\PhpWord\IOFactory:: createWriter($phpWord, "HTML");
$xmlWriter->save('a.html');

执行上面的代码就能生成html了,依然是迫不及待,生成的html跟unoconv类似,代码很多,转换为pdf格式不完美,所以任然不是很好的解决方案

总结

所以在尝试了unoconv、pandoc以及phpword之后,都不能得到相对简洁的对tcpdf友好的html,目前还没有尝试过付费方案,如果有必要,可以考虑再调研一下。

其他想法

又想到了word直接转pdf,首先对于word模板文档,我们可以把留白用phpword读取出来(留白有特殊标识),单独配置一个表单填写留白,用户添加完成后,再由phpword写入进去,最终由unoconv生成pdf。

这样富文本编辑器可以去掉了,填写好的内容删改的时候,直接改表单内容就行。

貌似也是一种方案。

人是活的,需求可以沟通,在保证投入与产出成正比的情况下,各种方案都值得沟通与尝试。

(完)