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不然就悲剧了;当然如果直接存库的那就无所谓了

这次就先这样,自娱自乐,手下留情勿喷!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/167382.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pymysql连接Mariadb/Mysql出现错误(配置正确情况下)解决办法

场景&#xff1a;在kali中使用python中pymysql对Mariadb进行连接&#xff0c;在整个过程中配置全部正确&#xff0c;但是就是无法进行连接&#xff0c;提示结果如下&#xff1a; Access denied for user rootlocalhost解决办法&#xff1a;进入数据库中&#xff0c;将默认密码…

自然语言处理---huggingface平台使用指南

1 huggingface介绍 Huggingface总部位于纽约&#xff0c;是一家专注于自然语言处理、人工智能和分布式系统的创业公司。他们所提供的聊天机器人技术一直颇受欢迎&#xff0c;但更出名的是他们在NLP开源社区上的贡献。Huggingface一直致力于自然语言处理NLP技术的平民化(democr…

C# 文件 校验:MD5、SHA1、SHA256、SHA384、SHA512、CRC32、CRC64

文件 校验 算法&#xff1a;MD5、SHA1、SHA256、SHA384、SHA512、CRC32、CRC64 (免费) 编程语言&#xff1a;C# 功能&#xff1a;文件 哈希 属性 校验算法&#xff1a;MD5、SHA1、SHA256、SHA384、SHA512、CRC32、CRC64。 下载&#xff08;免费&#xff09;&#xff1a;htt…

瑞萨e2studio(27)----使用EZ-CUBE3烧录

瑞萨e2studio.27--使用EZ-CUBE3烧录 概述视频教学样品申请引脚配置EZ-CUBE3 仿真器开关设置对RA族MCU进行Flash编程蓝色 LED 指示灯的状态信息 概述 EZ-CUBE3&#xff08;CYRCNEZCUBE03&#xff09;是具有Flash存储器编程功能的片上调试仿真器&#xff0c;可以用于调试MCU程序…

Vue2基础知识(一) 认识Vue

&#x1f48c; 所属专栏&#xff1a;【Vue2】&#x1f600; 作 者&#xff1a;长安不及十里&#x1f4bb;工作&#xff1a;目前从事电力行业开发&#x1f308;目标&#xff1a;全栈开发&#x1f680; 个人简介&#xff1a;一个正在努力学技术的Java工程师&#xff0c;专注基础和…

【Javascript】构造函数之new的作用

目录 new的作用 把对象返回了回来 无new 有new 把构造函数的this指向了要返回的对象 无new​编辑 有new new的执行流程 new的作用 创建了新空对象将构造函数的作用域赋值给新对象(this指向新对象)执行构造函数代码 &#xff08;为这个新对象添加属性&#xff09;返回新对…

Java EE-使用Servlet搭建一个简单的前后端交互程序

上述前端和后端的代码如下&#xff1a; 前端&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"vie…

优测云测试平台 | 有效的单元测试

一、前言 本文作者提出了一种评价单元测试用例的质量的思路&#xff0c;即判断用例是否达到测试的“四大目标”。掌握识别好的用例的能力&#xff0c;可以帮助我们高效地写出高质量的测试用例。 评判冰箱的好坏&#xff0c;并不需要有制造一台冰箱的能力。在开始写测试用例之…

经典链表问题:解析链表中的关键挑战

这里写目录标题 公共子节点采用集合或者哈希采用栈拼接两个字符串差和双指针 旋转链表 公共子节点 例如这样一道题&#xff1a;给定两个链表&#xff0c;找出它们的第一个公共节点。 具体的题目描述我们来看看牛客的一道题&#xff1a; 这里我们有四种解决办法&#xff1a; …

晶振与晶体

文章目录 基础知识无源晶振 & 有源晶振 博文链接 基础知识 无源晶振 & 有源晶振 博文链接 晶振原理解析

Flutter的Constructors for public widgets should have a named ‘key‘ parameter警告

文章目录 问题描述问题原因修改方法详细解释 问题描述 Constructors for public widgets should have a named ‘key’ parameter. 如下图&#xff1a; 原本的代码 class MyTabPage extends StatefulWidget {override_MyTabPageState createState() > _MyTabPageState(…

大数据测试用例分析

基于大数据分析&#xff0c;对业务系统产生的日志进行智能分析&#xff0c;能够识别日志中的接口、参数、业务流&#xff0c;并依据分析的结果生成测试用例。 问题与背景 业务复杂 业务系统的复杂性&#xff0c;对测试人员的业务能力提出严格要求&#xff0c;加重测试成本。 …

【深度学习-第4篇】使用MATLAB快速实现CNN多变量回归预测

上一篇我们讲了使用CNN进行分类的MATLAB代码。 这一篇我们讲CNN的多变量回归预测。 是的&#xff0c;同样是傻瓜式的快速实现。 一、什么是多变量回归预测 多变量回归预测则是指同时考虑多个输入特征进行回归预测。举几个例子&#xff1a; 房价预测&#xff1a;给定一组房…

搜索问答技术学习:基于知识图谱+基于搜索和机器阅读理解(MRC)

目录 一、问答系统应用分析 二、搜索问答技术与系统 &#xff08;一&#xff09;需求和信息分析 问答需求类型 多样的数据源 文本组织形态 &#xff08;二&#xff09;主要问答技术介绍 发展和成熟度分析 重点问答技术基础&#xff1a;KBQA和DeepQA KBQA&#xff08;…

CentOS 系统安装和使用Docker服务

系统环境 使用下面的命令&#xff0c;可以查看CentOS系统的版本。 lsb_release -a结果&#xff1a; 说明我的系统是7.9.2009版本的 安装Docker服务 依次执行下面的指令&#xff1a; yum install -y yum-utilsyum install -y docker即可安装docker服务 如果这样安装不成功…

[ Windows-Nginx ]Windows服务器,Tomcat容器部署项目,整合Nginx

一、官网下载Nginx http://nginx.org/en/download.html 稳定版&#xff1a;windows的stable版本 注意&#xff1a;Nginx安装包不要放在中文目录下 二、conf目录下&#xff0c;修改nginx.conf文件 修改Nginx服务端口&#xff1a; 默认端口为80&#xff0c;即外界访问的入口…

mysql优化之explain详解

mysql的explain&#xff08;执行计划&#xff09;用于解释sql的执行的过程&#xff0c;然后把sql的执行过程用一张表格表示出来&#xff0c;它并不真正的执行sql&#xff0c;如下图。explain能够为我们优化sql提供很好参考作用。 下面我来看下执行计划表中各个字段是什么意思 i…

FFmpeg和rtsp服务器搭建视频直播流服务

下面使用的是ubuntu的&#xff0c;window系统可以参考&#xff1a; 通过rtsp-simple-server和ffmpeg实现录屏并发布视频直播_rtsp simple server_病毒宇宇的博客-CSDN博客 一、安装rtsp-simple-server &#xff08;1&#xff09;下载rtsp-simple-server 下载地址&#xff1a;R…

第 368 场 LeetCode 周赛题解

A 元素和最小的山形三元组 I 前后缀操作&#xff1a;求出前后缀上的最小值数组&#xff0c;然后枚举 j j j class Solution { public:int minimumSum(vector<int> &nums) {int n nums.size();vector<int> l(n), r(n);//l[i]min{nums[0],...,nums[i]}, r[i]mi…

二维码智慧门牌管理系统升级解决方案:突破传统,实现质检与抽检的个性化配置

文章目录 前言一、引入“独立质检”二、个性化抽检类别设定三、触发重采要素的功能升级四、升级优势与展望 前言 在数字化时代&#xff0c;智慧门牌管理系统已经成为社会管理的重要工具。为了满足各种复杂需求&#xff0c;系统升级是必然趋势。本次升级主要针对质检和抽检两大…