doc与docx文档转html,格式样式不变(包含图片转换)
最近做一个富文本的需求,要求把文档内容转换到富文本内,文档中的格式也好,样式也好,图片啥的都要一致展示;踩了不少坑,据说word文档其实是一个压缩包,我不是特别清楚但是也能理解,自己借鉴参考凑合看的,大佬勿喷
啥都不说了看代码吧;其中关于图片的导出有两种方式比较大的那种是用的jdk8自带的base
64搞的,大小有差别同一个图片的话我这个实测的图片是差200k左右,有要求的你可以换着来引用;jar的引用pom中有
<!--注意版本保持一致 poi poi-ooxml poi-scratchpad--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><!-- 操作doc ppt xls --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>4.1.2</version></dependency><!-- 操作docx pptx xlsx --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</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>
import fr.opensagres.poi.xwpf.converter.core.BasicURIResolver;
import fr.opensagres.poi.xwpf.converter.core.FileImageExtractor;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import sun.misc.BASE64Encoder;import javax.imageio.ImageIO;
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.*;
import java.util.Base64;/*** @author :Xiaoning Fan* @date :Created in 2023-10-16 下午 3:49* @description: 上传word文档并转换为html字符串返回,保持样式不变,图片替换为base64* @version: 1.0*/
@Slf4j
public class WordToHtmlStringConverter {/*** wordToHtml** @return* @throws IOException* @throws ParserConfigurationException* @throws TransformerException*/public static String wordToHtml(MultipartFile file) {
// 提取出word文档名称和后缀String filename = file.getOriginalFilename();try {if (filename.endsWith(".docx")) {// 将上传的文件传入Document转换return new WordToHtmlStringConverter().docxToHtmlText(file);} else if (filename.endsWith(".doc")) {return new WordToHtmlStringConverter().docToHtmlText(file);} else {log.error("不支持的文件格式!");return null;}} catch (FileNotFoundException e) {log.error("文件找不到异常!");e.printStackTrace();} catch (IOException e) {log.error("io转换异常!");e.printStackTrace();} catch (Exception e) {log.error("文件转换异常!");e.printStackTrace();}return null;}/*** 上传Word文档,返回解析后的Html*/public static String docToHtmlText(MultipartFile file) throws Exception {//使用字符数组流获取解析的内容ByteArrayOutputStream baos = new ByteArrayOutputStream();OutputStream outStream = new BufferedOutputStream(baos);try {//将上传的文件传入Document转换HWPFDocument wordDocument = new HWPFDocument(file.getInputStream());Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(document);//将读取到的图片上传并添加链接地址wordToHtmlConverter.setPicturesManager((imageStream, pictureType, name, width, height) -> {try {//首先要判断图片是否能识别if (pictureType.equals(PictureType.UNKNOWN)) {return "[不能识别的图片]";}//此处转换图片文件为Base64return Base64.getEncoder().encodeToString(imageStream).trim();} catch (Exception e) {log.info("upload exception", e);}return "[图片上传失败]";});// word文档转Html文档wordToHtmlConverter.processDocument(wordDocument);Document htmlDocument = wordToHtmlConverter.getDocument();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);String content = baos.toString();log.info("docToHtmlText--->{}", content);return content;} catch (Exception e) {log.error("docToHtmlText 异常", e);} finally {baos.close();outStream.close();}return null;}/*** 上传docx文档,返回解析后的Html*/public static String docxToHtmlText(MultipartFile file) throws Exception {ByteArrayOutputStream htmlStream = new ByteArrayOutputStream();ByteArrayOutputStream htmlImg = new ByteArrayOutputStream();String htmlStr = null;try {// 将上传的文件传入Document转换XWPFDocument docxDocument = new XWPFDocument(file.getInputStream());XHTMLOptions options = XHTMLOptions.create();// 设置图片存储路径String path = System.getProperty("java.io.tmpdir");String firstImagePathStr = path + "/" + System.currentTimeMillis();options.setExtractor(new FileImageExtractor(new File(firstImagePathStr)));options.URIResolver(new BasicURIResolver(firstImagePathStr));// 转换htmldocxDocument.createNumbering();XHTMLConverter.getInstance().convert(docxDocument, htmlStream, options);htmlStr = htmlStream.toString();String middleImageDirStr = "/word/media";String imageDirStr = firstImagePathStr + middleImageDirStr;File imageDir = new File(imageDirStr);String[] imageList = imageDir.list();if (imageList != null) {for (int i = 0; i < imageList.length; i++) {try {String oneImagePathStr = imageDirStr + "/" + imageList[i];File fileImage = new File(oneImagePathStr);if (fileImage.exists()) {log.info("处理图片开始。。。。。。。。");// 处理图片成为Base64格式// 读取图片字节数组InputStream in = new FileInputStream(fileImage);byte[] data = new byte[in.available()];in.read(data);String encode = new BASE64Encoder().encode(data);log.info("处理图片结束。。。。。。。" + encode);//修改文档中的图片信息htmlStr = htmlStr.replace(oneImagePathStr, "data:image/png;base64,"+encode);/* BufferedImage bi = ImageIO.read(fileImage);// 图片存储大小比较大ByteArrayOutputStream baos = new ByteArrayOutputStream();ImageIO.write(bi, "png", baos);byte[] bytes = baos.toByteArray();String sd = Base64.getEncoder().encodeToString(bytes).trim();log.info("处理图片结束。。。。。。。" + sd);htmlStr = htmlStr.replace(oneImagePathStr, "data:image/png;base64,"+sd);*/}} catch (Exception e) {log.info("upload docxToHtmlText exception", e);}}}log.info("处理结果:{}", htmlStr);} catch (Exception e) {log.error("docxToHtmlText 解析异常", e);} finally {if (htmlStream != null) {htmlStream.close();}return htmlStr;}}
}
直接引用就行,但是有一点,一定要注意接口返回的时候,如果直接返回页面接口上要加
@ResponseBody不然就悲剧了;当然如果直接存库的那就无所谓了

这次就先这样,自娱自乐,手下留情勿喷!!
相关文章:
doc与docx文档转html,格式样式不变(包含图片转换)
最近做一个富文本的需求,要求把文档内容转换到富文本内,文档中的格式也好,样式也好,图片啥的都要一致展示;踩了不少坑,据说word文档其实是一个压缩包,我不是特别清楚但是也能理解,自…...
CSS页面基本布局
前提回顾 1. 超文本标记语言(HTML)是一种标记语言,用来结构化我们的网页内容并赋予内容含义; (超文本标记语言(英语:HyperText Markup Language /ˈhaɪpətekst ˈmɑːkʌp ˈlŋɡwɪdʒ /…...
SQL查询命令互转vba格式
最近搞个Excel的vba查询数据库,发现vba有代码行长度限制需要转换下就弄了这个,布局和功能暂且这样了,哪位大佬如果有兴趣的可以再美化下! 这次更新了SQL命令互转VBA格式, SQL原始格式要分行的不能一坨贴进去࿰…...
android 指针动画转动
记录一种简单动画 效果图: 都是直接使用图片资源FrameLayout布局实现,布局如下: <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"…...
力扣第51题 N 皇后 c++ 难~ 回溯题
题目 51. N 皇后 困难 相关标签 数组 回溯 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ࿰…...
【摄影】基础笔记
摄影基础 合理选择器材1.定焦镜(画质更好,有利于联系构图)2.变焦镜(拍摄便捷灵活,有利于快速捕捉)3.了解焦距 合理利用景深1.焦段2.光圈3.背景距离 焦距与参数实用相机参数设置指南高效的快速对焦法&#x…...
【广州华锐互动】VR石油钻井井控实训系统
在过去的几十年中,石油工业的发展速度一直在加快。为了适应这个快速发展的行业,需要新的技术和工具,而VR(虚拟现实)技术正是其中之一。本文将探讨VR石油钻井井控实训系统在石油工业教育中的应用。 在真实的钻井环境中&…...
【RocketMQ系列五】消息示例-顺序消息延迟消息广播消息的实现
1. 前言 上一篇文章我们介绍了简单消息的实现,本文将主要来介绍顺序消息的实现,顺序消息分为局部顺序消息和全局顺序消息。 顺序消息指的是消费者在消费消息时,按照生产者发送消息的顺序进行消费。即先发送的先消费【FIFO】。 顺序消息分为…...
hdfs dfsadmin -safemode无法退出安全模式
退出安全模式 第一种:正常退出安全模式 hdfs dfsadmin -safemode leave如提示Safe mode is OFF,那就说明退出成功,但有时候这个命令也没办法退出安全模式,就需要使用强制退出 第二种:强制退出安全模式 hdfs dfsadmin …...
git 新建 branch 推送 到服务器
通常情况下,需要开发一个模块,从 master 新建立了一个 分支,newbranch,如果推送到服务器; 1:从远程 master 建立本地分支 newbranch; git checkout -b newbranch origin/master 2:当修改完成代码…...
安全渗透测试基础知识之网络基础知识
一、OSI七层模型 7应用层6表示层5会话层4传输层3网络层2数据链路层1物理层1.物理层 提供通信介质和接口标准 网线 2.网络链路层 提供二层寻扯/MAC地址和二层通信(交换机)功能 协议:以太网Ethernet 3.网络层 提供三层寻扯/IP地址和三层通信(路由器...
Unity Editor 打包指定资源(AssetBundle)和加载指定资源
前言: 一般用于ui资源打包和加载,代码比较简单没什么好说的,直接上代码。 打包代码: [MenuItem("Assets/打包指定的预设")]public static void BuildAsset() {var selectObject Selection.activeObject;if (selectObje…...
网站批量替换关键词方法
注意替换操作之前先对文件做好备份 1.下载http://downinfo.myhostadmin.net/ultrareplace5.02.rar 解压出来,运行UltraReplace.exe 2.点击菜单栏中的配置,全选所有文件类型,或者根据自己的需求选择部分,如htm、html、php、asp等 3.若替换单个文件,点击文件,若是要…...
RabbitMQ的LazyQueue
在默认情况下,RabbitMQ会将接收到的信息保存在内存中以降低消息收发的延迟。但在某些特殊情况下,这会导致消息积压,比如: 消费者宕机或出现网络故障消息发送量激增,超过了消费者处理速度消费者处理业务发生阻塞 一旦…...
面试经典150题——Day16
文章目录 一、题目二、题解 一、题目 42. Trapping Rain Water Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining. Example 1: Input: height [0,1,0,2,1,0,1,3,2,1,2,…...
从零开始搭建第一个django项目
目录 配置环境创建 Django 项目和 APP项目组成 子目录文件组成应用文件组成 配置 settings.py启动项目 数据表创建models.pyDjango-models的常用字段和常用配置 Django-admin 引入admin后台和管理员外键views.pyurls.pypostman接口测试 QuerySetInstance功能APIView 的概念…...
Godot2D角色导航-自动寻路教程(Godot获取导航路径)
文章目录 开始准备获取路径全局点坐标 开始准备 首先创建一个导航场景,具体内容参考下列文章: Godot实现角色随鼠标移动 然后我们需要设置它的导航目标位置,具体关于位置的讲解在下面这个文章: Godot设置导航代理的目标位置 获取…...
用c++写一个高精度计算的减法运算
这段代码是一个用C编写的程序,它实现了两个大整数的减法运算。 #include<iostream> #include<cstdio> #include<cstring> using namespace std;int main(){int a[256],b[256],c[256],lena,lenb,lenc,i;char n[256],n1[256]"1001",n2[2…...
基于白鲸优化的BP神经网络(分类应用) - 附代码
基于白鲸优化的BP神经网络(分类应用) - 附代码 文章目录 基于白鲸优化的BP神经网络(分类应用) - 附代码1.鸢尾花iris数据介绍2.数据集整理3.白鲸优化BP神经网络3.1 BP神经网络参数设置3.2 白鲸算法应用 4.测试结果:5.M…...
Matlab遗传算法工具箱——一个例子搞懂遗传算法
解决问题 我们一般使用遗传算法是用来处理最优解问题的,下面是一个最优解问题的例子 打开遗传算法工具箱 ①在Matlab界面找到应用程序选项,点击应用程序(英文版的Matlab可以点击App选项) ②找到Optimization工具箱,点击打开 创建所需要…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
