关于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 3if (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>// 设置XHTMLOptionsXHTMLOptions 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; // 返回图片路径}});// 处理文档内容,转换为 HTMLwordToHtmlConverter.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-8serializer.setOutputProperty(OutputKeys.INDENT, "yes"); // 格式化输出serializer.setOutputProperty(OutputKeys.METHOD, "html"); // 输出格式为 HTMLserializer.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 文件,便于阅读和使用。
相关文章:
关于java实现word(docx、doc)转html的解决方案
最近在研究一些关于文档转换格式的方法,因为需要用在开发的一个项目上,所以投入了一些时间,给大家聊下这块逻辑及解决方案。 一、关于word转换html大致都有哪些方法? (1)使用 Microsoft Word 导出 其实该…...
【8】思科IOS AP升级操作
1.概述 本文主要针对思科AP的升级操作进行记录,思科的AP目前主要分为IOS和COS AP,IOS AP是我们常见的AP3502/AP1602/AP2702等等型号的AP,而COS AP是AP2802/3802等型号的AP。当然这里所指的都是一些室内AP,如AP1572等室外AP也同样适用。本文先对IOS AP的升级操作进行总结,…...
【ROS2】RViz2界面类 VisualizationFrame 详解
1、简述 VisualizationFrame 继承自 QMainWindow 和 WindowManagerInterface; 窗口顶部是常规布局:菜单栏 和 工具栏 窗口中心是 RenderPanel,用来渲染3D画面 周围是dock区域,包括:DisplaysPanel、ViewsPanel、TimePanel、SelectionPanel 和 ToolPropertiesPanel Windo…...
2025年01月24日Github流行趋势
项目名称:shadPS4 项目地址url:https://github.com/shadps4-emu/shadPS4项目语言:C历史star数:15576今日star数:653项目维护者:georgemoralis, psucien, squidbus, raphaelthegreat, DanielSvoboda项目简介…...
Gradle buildSrc模块详解:集中管理构建逻辑的利器
文章目录 buildSrc模块二 buildSrc的使命三 如何使用buildSrc1. 创建目录结构2. 配置buildSrc的构建脚本3. 编写共享逻辑4. 在模块中引用 四 典型使用场景1. 统一依赖版本管理2. 自定义Gradle任务 3. 封装通用插件4. 扩展Gradle API 五 注意事项六 与复合构建(Compo…...
【Airsim 仿真】查找配置文件 settings json 的路径优先级
Airsim 查找配置文件 settings.json 的路径优先级 参考官方文档 Settings - AirSim 文件格式要求 settings.json 文件采用常规的 JSON 格式。在首次启动时,AirSim 会在用户的主文件夹中创建一个没有设置的 settings.json 文件(待测试)。为…...
【FreeRTOS 教程 四】队列创建与发布项目到队列
目录 一、FreeRTOS队列: (1)队列介绍: (2)用户模型说明: (3)阻塞队列: 二、队列管理 API: (1)uxQueueMessagesWaiti…...
STM32项目分享:智能厨房安全检测系统
目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片: 哔哩哔哩视频链接: STM32智能厨房安全检测系统 (资料分…...
2025美赛数学建模MCM/ICM选题建议与分析,思路+模型+代码
2025美赛数学建模MCM/ICM选题建议与分析,思路模型代码,详细更新见文末名片 一、问题A:测试时间:楼梯的恒定磨损(Archaeological Modeling) 适合专业:考古学、历史学、数学、机械工程 难度:中等…...
高并发问题的多维度解决之道
…...
Ubuntu环境 nginx 源码 编译安装
ubuntu 终端 使用 wget 下载源码 sudo wget http://nginx.org/download/nginx-1.24.0.tar.gz解压刚下载的源码压缩包 nginx-1.24.0.tar.gz sudo tar -zxvf nginx-1.24.0.tar.gz 解压完成 产生 nginx-1.24.0 目录 进入该目录 cd ./nginx-1.24.0 目录下有一个可执行文件 con…...
K8S中的数据存储之基本存储
基本存储类型 EmptyDir 描述:当 Pod 被调度到节点上时,Kubernetes 会为 Pod 创建一个空目录,所有在该 Pod 中的容器都可以访问这个目录。特点: 生命周期与 Pod 绑定,Pod 删除时,数据也会丢失。适用于临时…...
编码器和扩散模型
目录 摘要abstract1.自动编码器2.变分编码器(VAE)3.论文阅读3.1 介绍3.2 方法3.3 结论 4.总结参考文献 摘要 本周学习了自动编码器(AE)和变分自动编码器(VAE)的基本原理与实现,分析其在数据降维…...
PAT甲级-1024 Palindromic Number
题目 题目大意 一个非回文数,加上它的翻转数所得的和,进行k次,有可能会得到一个回文数。给出一个数n,限制相加次数为k次,如果小于k次就得到回文数,那么输出该回文数和相加的次数;如果进行k次还…...
FS8405 Release FS0B
复位场景:FS8405正常工作后,RSTB后期产生拉低复位信号。 1 故障与PGOOD、RSTB和FS0B引脚的联系 FS8405出现故障时,会对PGOOD、RSTB和FS0B引脚产生不同的影响,具体影响如下: 橙色标记,反应是不可配置的。…...
IGBT的损耗计算的学习【2025/1/24】
可以通过示波器实测IGBT电压电流波形,然后通过示波器的math功能将电压电流波形乘积后积分求损耗。 软开管:给了导通信号,但是电流并没有从此IGBT流过 IGBT(绝缘栅双极晶体管)的损耗主要分为 导通损耗 和 开关损耗 两部…...
Unity|小游戏复刻|见缝插针1(C#)
准备 创建Scenes场景,Scripts脚本,Prefabs预制体文件夹 修改背景颜色 选中Main Camera 找到背景 选择颜色,一种白中透黄的颜色 创建小球 将文件夹里的Circle拖入层级里 选中Circle,位置为左右居中,偏上&…...
No.1|Godot|俄罗斯方块复刻|棋盘和初始方块的设置
删掉基础图标新建assets、scenes、scripts文件夹 俄罗斯方块的每种方块都是由四个小方块组成的,很适合放在网格地图中 比如网格地图是宽10列,高20行 要实现网格的对齐和下落 Node2D节点 新建一个Node2D 添加2个TileMapLayer 一个命名为Board&…...
SSM框架探秘:Spring 整合 SpringMVC 框架
搭建和测试 SpringMVC 的开发环境: web.xml 元素顺序: 在 web.xml 中配置 DisPatcherServlet 前端控制器: <!-- 配置前端控制器 --> <servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>…...
2025.1.20——二、buuctf BUU UPLOAD COURSE 1 1 文件上传
题目来源:buuctf BUU UPLOAD COURSE 1 1 目录 一、打开靶机,查看信息 二、解题思路 step 1:上传一句话木马.php文件康康回显 step 2:蚁剑连接 三、小结 一、打开靶机,查看信息 这里提示到了文件会被上传到./uplo…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
