关于java实现word(docx、doc)转html的解决方案
最近在研究一些关于文档转换格式的方法,因为需要用在开发的一个项目上,所以投入了一些时间,给大家聊下这块逻辑及解决方案。
一、关于word转换html大致都有哪些方法?
(1)使用 Microsoft Word 导出
其实该方法就是使用word本身导出方案
操作步骤:
- 在 Microsoft Word 中打开文档。
- 点击 文件 > 另存为 或 导出。
- 选择保存类型为 网页(.html, .htm)。
- 保存文件后,会生成一个 HTML 文件(有时会附带一个文件夹用于存放图片等资源)。
优点:
- 保留了文档的大部分格式。
- 操作简单,无需其他工具。
缺点:
- 导出的 HTML 文件代码较冗余,包含许多与 Word 相关的样式和标签。
(2)使用第三方工具或在线转换工具
一般常见的有SmallPDF、Zamzar、Convertio、LibreOffice等在线工具或软件进行转换
优点:
- 方便快捷,适合大多数人使用。
- 有些工具可以清理冗余代码,生成更简洁的 HTML。
缺点:
- 在线工具可能存在隐私和安全风险。
- 某些工具可能无法完全保留复杂文档的格式。
(3)使用编程实现自动化转换
常见的编程实现有:
- Python:
- 使用
python-docx
库读取 .docx 文件,再用自定义逻辑生成 HTML。 - 使用
mammoth
库,专门将 .docx 转为干净的 HTML(推荐)。 - 使用
pywin32
调用 Windows COM 接口操作 Microsoft Word。
- 使用
- Java:
- 使用 Apache POI 的
XWPF
模块解析 .docx 文件并输出 HTML。
- 使用 Apache POI 的
- Node.js:
- 使用
officegen
或mammoth.js
转换 .docx 文件。
- 使用
- C#:
- 使用 OpenXML SDK 或 Interop.Word 来操作 Word 文件并转换为 HTML。
本此讲解的就是通过java的poi内的模块进行解析输出html
二、docx转换html
示例代码如下:
public static void docxtoHtml(String fileName, String outPutFile) throws TransformerException, IOException, ParserConfigurationException {
long startTime = System.currentTimeMillis();
XWPFDocument document = new XWPFDocument(new FileInputStream(fileName));
// 用于存储目录内容
StringBuilder toc = new StringBuilder();
toc.append("<div id='toc'>\n<ul>\n"); // 直接从 <ul> 开始,表示目录
// 遍历文档中的段落,查找目录项
List<XWPFParagraph> paragraphs = document.getParagraphs();
int tocLevel = 0; // 目录的当前级别,1代表一级目录,2代表二级目录,3代表三级目录
boolean tocStarted = false; // 标记目录是否开始
for (XWPFParagraph paragraph : paragraphs) {
String style = paragraph.getStyle(); // 获取段落样式
String text = paragraph.getText(); // 获取段落文本
// 根据段落的样式级别来识别目录项,假设标题样式为 Heading 1, Heading 2, Heading 3
if (style != null) {
if (style.equals("Heading 1")) { // 一级标题
if (tocStarted) {
toc.append("</ul>\n"); // 关闭上一级目录
}
toc.append("<ul>\n"); // 开始一个新的无序列表
toc.append("<li><a href='#" + text.hashCode() + "'>" + text + "</a></li>\n");
tocLevel = 1;
tocStarted = true;
} else if (style.equals("Heading 2")) { // 二级标题
if (tocLevel == 1) {
toc.append("<ul>\n"); // 开始二级目录
}
toc.append("<li><a href='#" + text.hashCode() + "'>" + text + "</a></li>\n");
tocLevel = 2;
} else if (style.equals("Heading 3")) { // 三级标题
if (tocLevel == 2) {
toc.append("<ul>\n"); // 开始三级目录
}
toc.append("<li><a href='#" + text.hashCode() + "'>" + text + "</a></li>\n");
tocLevel = 3;
}
}
// 在目录项前插入锚点
if (style != null && (style.equals("Heading 1") || style.equals("Heading 2") || style.equals("Heading 3"))) {
String anchor = "<a name='" + text.hashCode() + "'></a>";
String modifiedText = anchor + text; // 在目录项文本前添加锚点
// 更新段落中的文本
for (XWPFRun run : paragraph.getRuns()) {
run.setText(modifiedText, 0); // 更新段落内容
}
}
}
// 如果目录结束后,确保关闭所有的<ul>标签
if (tocLevel > 0) {
toc.append("</ul>\n");
}
toc.append("</ul>\n</div>\n"); // 关闭最外层的 <ul> 和 <div>
// 设置XHTMLOptions
XHTMLOptions options = XHTMLOptions.create().indent(4);
File imageFolder = new File(tempPath); // 图片临时文件夹路径
options.setExtractor(new FileImageExtractor(imageFolder));
options.URIResolver(new FileURIResolver(imageFolder));
// 使用 `XHTMLConverter` 进行 DOCX 到 HTML 的转换
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
XHTMLConverter.getInstance().convert(document, byteArrayOutputStream, options);
System.out.println("Generate " + outPutFile + " with " + (System.currentTimeMillis() - startTime) + " ms.");
// 获取转换后的HTML内容
String htmlContent = new String(byteArrayOutputStream.toByteArray(), "UTF-8");
// 将TOC插入到HTML的开头
htmlContent = toc + htmlContent;
// 处理分页符:将分页符添加到HTML中
htmlContent = htmlContent.replaceAll("<!-- PAGE_BREAK -->", "<div class='page-break'></div>");
// 添加表格样式(边框)
htmlContent = htmlContent.replaceAll("<table>", "<table style='border: 1px solid black !important; border-collapse: collapse; width: 100%;'>");
htmlContent = htmlContent.replaceAll("<td>", "<td style='border: 1px solid black !important; padding: 5px; text-align: left;'>");
htmlContent = htmlContent.replaceAll("<th>", "<th style='border: 1px solid black !important; padding: 5px; text-align: left;'>");
htmlContent = htmlContent.replaceAll("<tr>", "<tr style='border: 1px solid black !important;'>");
htmlContent = htmlContent.replaceAll("<thead>", "<thead style='border: 1px solid black !important;'>");
htmlContent = htmlContent.replaceAll("<tbody>", "<tbody style='border: 1px solid black !important;'>");
htmlContent = htmlContent.replaceAll("<tfoot>", "<tfoot style='border: 1px solid black !important;'>");
// 增加全局CSS样式(确保表格和目录样式正确)
String style = "<style>\n" +
"table { border: 1px solid black !important; border-collapse: collapse; width: 100%; }\n" +
"td, th { border: 1px solid black !important; padding: 5px; text-align: left; }\n" +
"tr { border: 1px solid black !important; }\n" +
"ul { list-style-type: none; padding: 0; }\n" + // 去掉默认的列表样式
"li { margin: 5px 0; }\n" + // 设置目录项的间距
"</style>\n";
htmlContent = style + htmlContent;
// 将最终的HTML内容写入文件
writeFile(htmlContent, outPutFile);
}
该方法功能实现:
- 将
.docx
文件转换为 HTML 文件。 - 自动生成基于文档标题的目录 (TOC)。
- 为标题添加锚点链接,支持 HTML 页面内跳转。
- 处理分页符,将其转换为 HTML 的
<div>
元素。 - 增强表格样式,添加边框和对齐(有时原表格css样式转换后会被覆盖掉)。
- 为 HTML 页面添加全局 CSS 样式,保证视觉效果统一。
三、doc转换html
示例代码如下:
public static void doctoHtml(String fileName, String outPutFile) throws TransformerException, IOException, ParserConfigurationException {
// 开始计时
long startTime = System.currentTimeMillis();
// 读取 Word 文档
HWPFDocument wordDocument = new HWPFDocument(new FileInputStream(fileName));
// 创建 Word 转 HTML 转换器
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
// 图片保存路径设置
String imageFolderPath = tempPath + "images" + File.separator; // 存储图片的绝对路径
// 设置图片管理器,处理图片保存逻辑
wordToHtmlConverter.setPicturesManager(new PicturesManager() {
public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, float heightInches) {
String picturePath = imageFolderPath + suggestedName; // 图片保存路径
File imageFolder = new File(imageFolderPath);
if (!imageFolder.exists()) {
boolean created = imageFolder.mkdirs(); // 创建图片文件夹
if (created) {
System.out.println("在以下位置创建图片文件夹:" + imageFolder.getAbsolutePath());
} else {
System.out.println("创建图片文件夹失败");
}
}
try {
File pictureFile = new File(picturePath);
try (FileOutputStream fos = new FileOutputStream(pictureFile)) {
fos.write(content); // 写入图片数据
System.out.println("图片保存路径" + pictureFile.getAbsolutePath());
}
} catch (IOException e) {
e.printStackTrace();
}
return picturePath; // 返回图片路径
}
});
// 处理文档内容,转换为 HTML
wordToHtmlConverter.processDocument(wordDocument);
// 获取生成的 HTML 文档
Document htmlDocument = wordToHtmlConverter.getDocument();
// 自定义分页符处理:查找文档中的分页符并插入到 HTML 中
NodeList bodyNodes = htmlDocument.getElementsByTagName("body");
if (bodyNodes.getLength() > 0) {
Node bodyNode = bodyNodes.item(0); // 获取 HTML 中的 <body> 节点
NodeList paragraphs = bodyNode.getChildNodes();
for (int i = 0; i < paragraphs.getLength(); i++) {
Node paragraph = paragraphs.item(i);
if (paragraph.getNodeType() == Node.ELEMENT_NODE && paragraph.getNodeName().equals("p")) {
String innerText = paragraph.getTextContent();
if (innerText.contains("\f")) { // 检查是否包含分页符(\f)
// 创建自定义分页符 HTML 元素
Element pageBreak = htmlDocument.createElement("div");
pageBreak.setAttribute("class", "page-break"); // 设置 class 属性,方便样式控制
pageBreak.appendChild(htmlDocument.createTextNode(" "));
// 在分页符前插入自定义分页符标记
bodyNode.insertBefore(pageBreak, paragraph);
}
}
}
}
// 将 HTML 文档输出为字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(out);
// 使用 Transformer 进行 HTML 格式化输出
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); // 设置编码为 UTF-8
serializer.setOutputProperty(OutputKeys.INDENT, "yes"); // 格式化输出
serializer.setOutputProperty(OutputKeys.METHOD, "html"); // 输出格式为 HTML
serializer.transform(domSource, streamResult);
out.close();
// 将字节流转换为字符串
String htmlContent = new String(out.toByteArray());
// 处理特殊标记符,例如去掉目录标记(根据需要调整)
htmlContent = htmlContent.replaceAll("TOC \\\\o \"1-3\" \\\\h \\\\z \\\\u", "");
// 将生成的 HTML 内容写入文件
writeFile(htmlContent, outPutFile);
// 输出生成文件的信息及用时
System.out.println("Generate " + outPutFile + " with " + (System.currentTimeMillis() - startTime) + " ms.");
}
该方法功能实现:
- 将
.doc
格式的 Word 文档转换为 HTML 文件。 - 提取并保存文档中的图片到指定路径,并在 HTML 中插入图片引用。
- 处理分页符,将分页符(
\f
)替换为自定义的 HTML 标记。 - 格式化生成的 HTML 文件,便于阅读和使用。