word文档转html格式在线预览,使用了phpoffice

最近客户要做一个word,excel 文件在线预览功能,以下是实现此功能的全过程。
由于我们用的是PHP开发项目,最开始想到的是用PHPoffice里的phpword来进行转换,以下是关键代码。

1
2
3
4
php复制代码<?php
$phpWord = \PhpOffice\PhpWord\IOFactory::load('test.doc');
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, "HTML");
$xmlWriter->save('test.html);

用这种方法转是可以转,但是转出来的html文件相对原文件,丢失了很多字,如果说样式和原文不一样还可以忍受,但是内容丢失,就不太好了,而且对DOC格式又无法处理,所以这种方法,我最终选择了放弃。
然后,我就想用python来解决这个问题,查到了python有个pydocx库可以处理word文档,于是我就安装了一下。

1
复制代码pip install pydocx

这个库用起来也很简单,主要代码如下:

1
2
3
4
5
ini复制代码from pydocx import PyDocX
html = PyDocX.to_html("test2.doc")
f = open("test.html", 'w', encoding="utf-8")
f.write(html)
f.close()

转换效果也还可以,除了表格样式和原文有点不一样以外,内容倒是没丢失,但是有一个问题,这个库是转换docx的,对doc转换不了,我们客户还上传挺多doc格式的文件的,于是我只好另外想办法。
查资料发现java有个poi库可以用来对word文件进行转换, Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。我想试一下,查资料半天,就开始写了,先Maven引入依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
xml复制代码    <dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 针对2003版本的库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.poi.xwpf.converter.xhtml</artifactId>
<version>2.0.2</version>
</dependency>
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.4.3</version></dependency>
</dependencies>

以下是引用别人的可用代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
ini复制代码import cn.hutool.core.img.ImgUtil;
import fr.opensagres.poi.xwpf.converter.xhtml.Base64EmbedImgManager;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.image.BufferedImage;
import java.io.*;
/**
* office转换工具测试
*
*/
public class OfficeConvertUtil {

/**
* 将word2003转换为html文件 2017-2-27
*
* @param wordPath word文件路径
* @param wordName word文件名称无后缀
* @param suffix word文件后缀
* @throws IOException
* @throws TransformerException
* @throws ParserConfigurationException
*/
public static String Word2003ToHtml(String wordPath, String wordName,
String suffix) throws IOException, TransformerException,
ParserConfigurationException {
String htmlPath = wordPath + File.separator + "html"
+ File.separator;
String htmlName = wordName + ".html";
final String imagePath = htmlPath + "image" + File.separator;

// 判断html文件是否存在,每次重新生成
File htmlFile = new File(htmlPath + htmlName);
// if (htmlFile.exists()) {
// return htmlFile.getAbsolutePath();
// }

// 原word文档
final String file = wordPath + File.separator + wordName + suffix;
InputStream input = new FileInputStream(new File(file));
HWPFDocument wordDocument = new HWPFDocument(input);
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.newDocument());

wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> {
BufferedImage bufferedImage = ImgUtil.toImage(content);
String base64Img = ImgUtil.toBase64(bufferedImage, pictureType.getExtension());
// 带图片的word,则将图片转为base64编码,保存在一个页面中
StringBuilder sb = (new StringBuilder(base64Img.length() + "data:;base64,".length()).append("data:;base64,").append(base64Img));
return sb.toString();
});

// 解析word文档
wordToHtmlConverter.processDocument(wordDocument);
Document htmlDocument = wordToHtmlConverter.getDocument();
// 生成html文件上级文件夹
File folder = new File(htmlPath);
if (!folder.exists()) {
folder.mkdirs();
}

// 生成html文件地址
OutputStream outStream = new FileOutputStream(htmlFile);

DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(outStream);

TransformerFactory factory = TransformerFactory.newInstance();
Transformer serializer = factory.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");

serializer.transform(domSource, streamResult);

outStream.close();

return htmlFile.getAbsolutePath();
}

/**
* 2007版本word转换成html 2017-2-27
*
* @param wordPath word文件路径
* @param wordName word文件名称无后缀
* @param suffix word文件后缀
* @return
* @throws IOException
*/
public static String Word2007ToHtml(String wordPath, String wordName, String suffix)
throws IOException {
ZipSecureFile.setMinInflateRatio(-1.0d);
String htmlPath = wordPath + File.separator + "html"
+ File.separator;
String htmlName = wordName + ".html";
String imagePath = htmlPath + "image" + File.separator;

// 判断html文件是否存在
File htmlFile = new File(htmlPath + htmlName);
// if (htmlFile.exists()) {
// return htmlFile.getAbsolutePath();
// }

// word文件
File wordFile = new File(wordPath + File.separator + wordName + suffix);

// 1) 加载word文档生成 XWPFDocument对象
InputStream in = new FileInputStream(wordFile);
XWPFDocument document = new XWPFDocument(in);

// 2) 解析 XHTML配置 (这里设置IURIResolver来设置图片存放的目录)
File imgFolder = new File(imagePath);
// 带图片的word,则将图片转为base64编码,保存在一个页面中
XHTMLOptions options = XHTMLOptions.create().indent(4).setImageManager(new Base64EmbedImgManager());
// 3) 将 XWPFDocument转换成XHTML
// 生成html文件上级文件夹
File folder = new File(htmlPath);
if (!folder.exists()) {
folder.mkdirs();
}
OutputStream out = new FileOutputStream(htmlFile);
XHTMLConverter.getInstance().convert(document, out, options);

return htmlFile.getAbsolutePath();
}
public static void main(String[] args) throws Exception {
System.out.println(Word2003ToHtml("D:\\tmp", "test", ".doc"));
System.out.println(Word2007ToHtml("D:\\tmp", "test2", ".docx"));
}
}

用java 倒是转换doc格式转的挺好的,但是转换docx格式的时候,样式全乱了,我查了半天POI的文档,网上也没有哪位大佬来解决这个样式乱的问题,于是我想用python来转docx ,java来转doc,但是又觉得太麻烦。
在查了半天资料以后,我最终的解决办法如下。
还是回到了用php处理,但是不是用phpoffice来处理,而是用unocov进行转换,先装libreoffice

1
复制代码yum install libreoffice

然后装unocov

1
复制代码yum install unoconv

用以下命令就可以转换了

1
css复制代码unoconv -f html -o test.html test.doc

-f是输出格式,-o是输出文件 最后面是输入文件,具体用法可以查相关文档,我在php里执行外部命令,生成转换好的文件以后再重定向到生成的文件上面去,由于excel 转html报错,所以我针对excel 转成了pdf.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bash复制代码        if (file_exists($source)) {
$dir = dirname($source);
$ext=pathinfo($source)['extension'];
if(!in_array($ext,['xls','xlsx'])){
$filetype='html';
}else $filetype='pdf';
$filename = strstr(basename($source), '.', true) . '.'.$filetype;
$file = $filename;
if(!file_exists('data/' . $file)){
//echo "sudo /usr/bin/unoconv -f {$filetype} -o " . '/data/web/public/data/' . $file . ' ' . '/data/web/data_manage/public/' . $source;exit;
$res= shell_exec("sudo /usr/bin/unoconv -f {$filetype} -o " . '/data/web/public/data/' . $file . ' ' . '/data/web/data_manage/public/' . $source);
if(!file_exists('data/' . $file)){
dump($res);
exit('生成预览文件出错');
}
}
header("Location:".'/data/' . $file);
exit();
} else exit('文件不存在');

最后,总算是把doc,docx 还有excel文件,wps文件都能预览出来,样式还是有点变化,内容没有丢失,客户也还算是能接受,以上是我解决这个问题的心得,希望能帮到大家。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%