Content Table

Doc 转换为 HTML

上传 doc 文件到服务器上时,如果需要在浏览器中预览,可以把 doc 转为 pdf,然后使用 pdf.js 在线预览 pdf,也可以把 doc 转为 html,直接在浏览器中打开。POI 可以很简单的把 doc 转为 html。

Word 里的公式使用的矢量格式 WMF,需要转换为 SVG 后才能在浏览器中查看,下面的代码使用了 wmf2svg 进行了转换。发现图片文件的名字以 .wmf 结尾,则给它加上 .svg,并且转换为 SVG 格式的图片。

Gradle 依赖

1
2
3
compile 'commons-io:commons-io:2.5'
compile 'org.apache.poi:poi-scratchpad:3.16'
compile 'net.arnx:wmf2svg:0.9.8'

转换程序

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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import net.arnx.wmf2svg.gdi.svg.SvgGdi;
import net.arnx.wmf2svg.gdi.wmf.WmfParser;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.List;

/**
* 把 doc 转换为 html 的工具类
*/
public class DocToHtmlUtils {
/**
* 使用 UTF-8 编码,把 doc 文件为 html。
* html 存储在目录 htmlDir,名字为 index.html,html 的图片存储在目录 htmlDir/img 中。
*
* @param docFile doc 文件
* @param htmlDir html 保存的目录
*/
public static void convertDocToHtml(File docFile, File htmlDir) throws Exception {
convertDocToHtml(docFile, htmlDir, "index.html", "img", "UTF-8");
}

/**
* 使用指定的编码,把 doc 文件为 html。
*
* @param docFile doc 文件
* @param htmlDir html 保存的目录
* @param htmlFileName 生成的 html 文件的名字
* @param imageDirName 生成的 html 的图片存储的目录名,它父目录是 htmlDir
* 如果 为 null,则说明图片和 html 文件存放在同一个文件夹下
* @param encoding 生成 html 文件的编码
* @throws Exception
*/
public static void convertDocToHtml(File docFile, File htmlDir, String htmlFileName, String imageDirName, String encoding) throws Exception {
// 创建 html 和其图片所在文件夹
File imgDir = htmlDir;

if (imageDirName == null || imageDirName.trim().equals("")) {
imageDirName = null;
} else {
imageDirName = imageDirName.trim();
imgDir = new File(htmlDir, imageDirName);
}

// 图片文件夹在 htmlDir 内,所以创建它的时候 htmlDir 已经保证先被创建
FileUtils.forceMkdir(imgDir);

// 转换 doc 为 html
HWPFDocument docDocument = new HWPFDocument(new FileInputStream(docFile));
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
WordToHtmlConverter docToHtmlConverter = new WordToHtmlConverter(doc);

final String imgDirName = imageDirName;
docToHtmlConverter.setPicturesManager(new PicturesManager() {
public String savePicture(byte[] content,
PictureType pictureType, String suggestedName,
float widthInches, float heightInches ) {
if (suggestedName.toLowerCase().endsWith(".wmf")) {
suggestedName += ".svg"; // 重命名为 xxx.wmf.svg,一会要把 .wmf 图片转换为 svg 的
}

// HTML 中图片的相对路径
return imgDirName == null ? suggestedName : imgDirName + File.separator + suggestedName;
}
} );

docToHtmlConverter.processDocument(docDocument);

// 保存图片
List<Picture> pictures = docDocument.getPicturesTable().getAllPictures();

if(pictures != null){
for (Picture picture : pictures) {
try {
String suggestedName = picture.suggestFullFileName();

// 如果是 wmf 图片,则转换为 svg
if (suggestedName.toLowerCase().endsWith(".wmf")) {
FileUtils.writeByteArrayToFile(new File(imgDir, suggestedName + ".svg"), convertWmfToSvg(picture));
} else {
picture.writeImageContent(new FileOutputStream(new File(imgDir, suggestedName)));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}

// 获取 html 内容
Document htmlDocument = docToHtmlConverter.getDocument();
ByteArrayOutputStream out = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(out);

TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, encoding);
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
out.close();

// 保存 index.html
FileUtils.writeByteArrayToFile(new File(htmlDir, htmlFileName), out.toByteArray());
}

/**
* Wmf 转化为 Svg
*
* @param wmfPicture
* @return Svg 内容的 bytes 数组
* @throws Exception
*/
public static byte[] convertWmfToSvg(Picture wmfPicture) throws Exception {
ByteArrayOutputStream wmfContent = new ByteArrayOutputStream();
wmfPicture.writeImageContent(wmfContent);

ByteArrayInputStream in = new ByteArrayInputStream(wmfContent.toByteArray());
ByteArrayOutputStream out = new ByteArrayOutputStream();
convertWmfToSvg(in, out);

return out.toByteArray();
}

/**
* 从传入的输入流 in 中读取 wmf 的内容,转换为 svg 格式的内容,保存到 out 中
*
* @param in wmf 的输入流
* @param out svg 的输出流
* @throws Exception
*/
public static void convertWmfToSvg(InputStream in, OutputStream out) throws Exception {
WmfParser parser = new WmfParser();
SvgGdi gdi = new SvgGdi(false);

parser.parse(in, gdi);
Document doc = gdi.getDocument();

// 保存到 ByteArrayOutputStream
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();

transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"-//W3C//DTD SVG 1.0//EN");
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd");

transformer.transform(new DOMSource(doc), new StreamResult(out));
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
transformer.transform(new DOMSource(doc), new StreamResult(buffer));
out.flush();
}

public static void main(String argv[]) throws Exception {
convertDocToHtml(new File("/Users/Biao/Desktop/2011届高考数学强化复习训练题11.doc"),
new File("/Users/Biao/Desktop/doc/x"));
// convertDocToHtml(new File("/Users/Biao/Desktop/doc/x.doc"),
// new File("/Users/Biao/Desktop/doc/y"),
// "goo.html", null, "UTF-8");
}
}