当前位置: 首页 > news >正文

java操作富文本插入到word模板

最近项目有个需求,大致流程是前端保存富文本(html的代码)到数据库,后台需要将富文本代码转成带格式的文字,插入到word模板里,然后将word转成pdf,再由前端调用接口下载pdf文件!

1、思路

这里的主要难点就是将html的格式带入到word里,所以这里要先将格式写入到html里。怎么写入到html里呢?这里提供一下思路,就是把你的word模板先转成html代码,为啥是代码不是html文件呢?因为我要用这个html代码去把富文本插进去,怎么插呢?首先要标记一个替换符在word模板里,这里有了替换符我们就可以用replace把富文本代码替换掉这个替换符,这样富文本就插进去了嘛!然后再把html代码转成word文档,再进行你的逻辑操作就可以了!
总结: 大致意思就是将word模板提取成html代码,再把富文本替换进去,然后把替换完的代码转成word。

2、依赖

主要就是用的aspose-words,因为好用所以一直在用,这里用aspose主要是文件的转换。我的业务逻辑需要把数据放到word指定的位置里,所以我要用替换的方式去替换数据,这里也用到了poi-tl。
贴一下我的版本,这里的aspose我是放到lib里了

依赖想下载的直接去下载:https://download.csdn.net/download/weixin_44953395/88565563
不要积分的

<!-- word转pdf-->
<dependency><groupId>com.aspose</groupId><artifactId>aspose-words</artifactId><version>15.8.0</version><scope>system</scope><systemPath>${project.basedir}/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
</dependency>
<!--poi-tl-->
<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.10.4</version>
</dependency>

3、代码

说了一堆废话,还是得看代码,谁也挡不住复制粘贴!

@Test
public void testDocToHtml() {String html = WordToPdfUtil.parseWord2Html("D:\\environment\\idea\\company\\ceshi\\test.docx");String fwb = "<ol><li>古诗</li></ol><p>《南歌子·似带如丝柳》</p><p><span style=\"color: rgb(212, 56, 13);\"><u>唐·温庭筠</u></span></p><p><span style=\"background-color: rgb(115, 209, 61);\">似带如丝柳,团酥握雪花。</span></p><p><span style=\"color: rgb(89, 126, 247);\">帘卷玉钩斜,九衢尘欲暮,逐香车。</span></p>";assert html != null;String fwbHtml = html.replaceAll("Fwb1", fwb);System.out.println(fwbHtml);WordToPdfUtil.htmlToWord(fwbHtml.getBytes(StandardCharsets.UTF_8), 20, "D:\\environment\\idea\\company\\ceshi\\ceshi.docx");
}
package com.byqh.utils;import com.aspose.words.*;import java.io.*;
import java.nio.charset.StandardCharsets;/*** word转Pdf帮助类* <p>* 备注:需要引入 aspose-words-15.8.0-jdk16.jar*/
public class WordToPdfUtil {private static boolean getLicense() {boolean result = false;try {InputStream is = WordToPdfUtil.class.getClassLoader().getResourceAsStream("license.xml");License asposeLic = new License();asposeLic.setLicense(is);result = true;} catch (Exception e) {e.printStackTrace();}return result;}/*** word转pdf* * @param wordPath 需要被转换的word全路径带文件名* @param pdfPath  转换之后pdf的全路径带文件名*/public static void docToPdf(String wordPath, String pdfPath) {// 验证License 若不验证则转化出的pdf文档会有水印产生if (!getLicense()) {return;}try {long old = System.currentTimeMillis();//新建一个pdf文档File file = new File(pdfPath);FileOutputStream os = new FileOutputStream(file);//wordPath是将要被转化的word文档Document doc = new Document(wordPath);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换doc.save(os, SaveFormat.PDF);long now = System.currentTimeMillis();os.close();//转化用时System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒");} catch (Exception e) {e.printStackTrace();}}/*** word转html文本** @param wordPath 需要转换的doc文件* @return html代码*/public static String parseWord2Html(String wordPath) {// 验证License 若不验证则转化出的pdf文档会有水印产生if (!getLicense()) {return null;}HtmlSaveOptions saveOptions = new HtmlSaveOptions();saveOptions.setExportHeadersFootersMode(ExportHeadersFootersMode.NONE); ByteArrayOutputStream htmlStream = new ByteArrayOutputStream();String htmlText = "";try {Document doc = new Document(wordPath);doc.save(htmlStream, saveOptions);htmlText = new String(htmlStream.toByteArray(), StandardCharsets.UTF_8);htmlStream.close();} catch (Exception e) {System.out.println(e.getMessage());}return htmlText;}/*** html字节数组转word字节数组** @param content  html字节数组* @param toType   值为SaveFormat.DOCX-20或SavaFormat.Doc-10对应的值* @param filePath 转换完成之后的文件路径*/public static void htmlToWord(byte[] content, Integer toType, String filePath) {// 验证License 若不验证则转化出的pdf文档会有水印产生if (!getLicense()) {return;}try {File file = new File(filePath);FileOutputStream os = new FileOutputStream(file);InputStream is = new ByteArrayInputStream(content);Document doc = new Document();DocumentBuilder builder = new DocumentBuilder(doc);InputStreamReader streamReader = new InputStreamReader(is, StandardCharsets.UTF_8);BufferedReader reader = new BufferedReader(streamReader);String line;StringBuilder html = new StringBuilder();while ((line = reader.readLine()) != null) {html.append(line);}reader.close();builder.insertHtml(String.valueOf(html));doc.save(os, toType);System.out.println("html转word成功!");} catch (Exception e) {System.out.println(e.getMessage());}}}

效果:

替换之前:(这里的Fwb1就是一个标志符)
在这里插入图片描述
替换之后:
在这里插入图片描述
这里的富文本是用的wangeditor,网站是:https://www.wangeditor.com/

写在富文本的样子是下图这样的,总体来说还可以!
在这里插入图片描述

4、替换

替换用的是poi-tl,它的网址说明文档:http://deepoove.com/

@Test
public void testDocTh() throws IOException {Map<String, Object> map = new HashMap<>();map.put("sj01", "测试-test01");map.put("sj02", "测试-test02");List<PictureRenderData> list = new ArrayList<>();//这里的size设置的是宽和高list.add(Pictures.ofStream(new FileInputStream("D:\\environment\\idea\\company\\ceshi\\400X350.png")).size(400, 350).create());list.add(Pictures.ofStream(new FileInputStream("D:\\environment\\idea\\company\\ceshi\\400X400.png")).size(400, 400).create());for (int i = 0; i < list.size(); i++) {map.put("tp0" + (i + 1), list.get(i));}XWPFTemplate template = XWPFTemplate.compile("D:\\environment\\idea\\company\\ceshi\\test.docx").render(map);FileOutputStream out1 = new FileOutputStream("D:\\environment\\idea\\company\\ceshi\\out_template.docx");template.write(out1);out1.close();
}

替换之前:
在这里插入图片描述
替换之后:
在这里插入图片描述
说明一下,这里的两张图片一个是400X350的一个是400X400的两个大小差不太多,所以大小不太明显!

相关文章:

java操作富文本插入到word模板

最近项目有个需求&#xff0c;大致流程是前端保存富文本&#xff08;html的代码&#xff09;到数据库&#xff0c;后台需要将富文本代码转成带格式的文字&#xff0c;插入到word模板里&#xff0c;然后将word转成pdf&#xff0c;再由前端调用接口下载pdf文件&#xff01; 1、思…...

JMeter---BeanShell实现接口前置和后置操作

在JMeter中&#xff0c;可以使用BeanShell脚本来实现接口的前置和后置操作。 下面是使用BeanShell脚本实现接口前置和后置操作的步骤&#xff1a; 1、在测试计划中添加一个BeanShell前置处理器或后置处理器。 右键点击需要添加前置或后置操作的接口请求&#xff0c;选择&quo…...

【Linux】共享内存

文章目录 一、共享内存的原理详谈共享内存的实现过程二、共享内存的接口函数1.shmget2. shmatshmdtshmctl 进程间使用共享内存通信三、共享内存的特性 关于代码 一、共享内存的原理 共享内存是由操作系统维护和管理的一块内存。 共享内存的本质是内核级的缓冲区。 一个进程向…...

五、双向NAT

学习防火墙之前&#xff0c;对路由交换应要有一定的认识 双向NAT1.1.基本原理1.2.NAT Inbound NAT Server1.3.域内NATNAT Server —————————————————————————————————————————————————— 双向NAT 经过前面介绍&#xff0c;…...

P1028 [NOIP2001 普及组] 数的计算

时刻记住一句话&#xff1a;写递归&#xff0c;1画图&#xff0c;2大脑放空&#xff01;&#xff01;&#xff01; 意思是&#xff0c;自己写递归题目&#xff0c;先用样例给的数据画图&#xff0c;然后想一个超级简单的思路&#xff0c;直接套上去就可以了。 上题干&#xff…...

浅析三相异步电动机控制的电气保护

安科瑞 华楠 摘 要&#xff1a;要求三相异步电动机的控制系统不仅要保证电机正常启动和运行&#xff0c;完成制动操作&#xff0c;还要通过相关保护措施维护电动机的安全使用。基于此&#xff0c;本文以电动机电气保护作为研究对象&#xff0c;结合三相异步电动机的机械特点&…...

Java设计模式系列:单例设计模式

Java设计模式系列&#xff1a;单例设计模式 介绍 所谓类的单例设计模式&#xff0c;就是采取一定的方法保证在整个的软件系统中&#xff0c;对某个类只能存在一个对象实例&#xff0c;并且该类只提供一个取得其对象实例的方法&#xff08;静态方法&#xff09; 比如 Hiberna…...

开拓新天地:探讨数位行销对医药产业医病连结的影响

数字营销模式多元&#xff0c;主要围绕医生和患者。赛道各企业凭借各自优势&#xff08;技术、学术、流量等&#xff09;入局&#xff0c;提供各自差异化营销工具或服务。目前&#xff0c;围绕医生的数字营销旨在为医生提供全面学术解决方案从而提升对医药产品的认可&#xff0…...

[tsai.shen@mailfence.com].faust勒索病毒数据怎么处理|数据解密恢复

导言&#xff1a; [support2022cock.li].faust、[tsai.shenmailfence.com].faust、[Encrypteddmailfence.com].faust勒索病毒是一种具有恶意目的的勒索软件&#xff0c;其主要特点包括对受害者文件进行强力加密&#xff0c;然后勒索受害者支付赎金以获取解密密钥。攻击者通常通…...

Peter算法小课堂—前缀和数组的应用

桶 相当于计数排序&#xff0c;看一个视频 桶排序 太戈编程1620题 算法解析 #include <bits/stdc.h> using namespace std; const int R11; int cnt[R];//cnt[t]代表第t天新增几人 int s[R];//s[]数组是cnt[]数组的前缀和数组 int n,t; int main(){cin>>n;for(…...

线性表之链式表

文章目录 主要内容一.单链表1.头插法建立单链表代码如下&#xff08;示例&#xff09;: 2.尾插法建立单链表代码如下&#xff08;示例&#xff09;: 3.按序号查找结点值代码如下&#xff08;示例&#xff09;: 4.按值查找表结点代码如下&#xff08;示例&#xff09;: 5.插入节…...

[Docker]十.Docker Swarm讲解

一.Dokcer Swarm集群介绍 1.Dokcer Swarm 简介 Docker Swarm 是 Docker 公司推出的用来管理 docker 集群的工具&#xff0c; 使用 Docker Swarm 可以快速方便的实现 高可用集群 ,Docker Compose 只能编排单节点上的容器, Docker Swarm 可以让我们在单一主机上操作来完成对 整…...

相机机模组需求示例

产品需求名称摄像头采集图片数据补充说明产品需求描述 As&#xff1a;用户 I want to&#xff1a;通过相机模组获取到自定义格式图片数据&#xff0c;要求包括&#xff1a; 1、支持多种场景&#xff0c;如&#xff1a;手持相机拍摄舌苔 2、支持图片分辨率至少达到1920X1080 3、…...

Uniapp 微信登录流程解析

本文将介绍在 Uniapp 应用中实现微信登录的流程&#xff0c;包括准备工作、授权登录、获取用户信息等步骤。 内容大纲&#xff1a; 介绍Uniapp和微信登录&#xff1a; 简要介绍 Uniapp 框架以及微信登录的重要性和流行程度。 准备工作&#xff1a; 注册微信开发者账号创建应用…...

红旗Asianux Server Linux V8 安装万里数据库(GreatSQL)

红旗Asianux Server Linux V8 安装万里数据库&#xff08;GreatSQL&#xff09; 红旗Asianux介绍&#xff1a; 红旗Asianux Server Linux 8.0是为云时代重新设计的操作系统&#xff0c;为云时代的到来引入了大量新功能&#xff0c;包括用于配置管理、快速迁移框架、编程语言和…...

一文2000字使用JMeter进行接口测试教程!(建议收藏)

安装 使用JMeter的前提需要安装JDK&#xff0c;需要JDK1.7以上版本目前在用的是JMeter5.2版本&#xff0c;大家可自行下载解压使用 运行 进入解压路径如E: \apache-jmeter-5.2\bin&#xff0c;双击jmeter.bat启动运行 启动后默认为英文版本&#xff0c;可通过Options – Cho…...

Spark---介绍及安装

一、Spark介绍 1、什么是Spark Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop MapReduce的通用并行计算框架&#xff0c;Spark拥有Hadoop MapReduce所具有的优点&#xff1b;但…...

uni-app:实现request请求的递归(设置request请求的访问次数),并且调用自定义方法给出返回值

一、效果展示 失败效果 成功效果 二、写入后端请求部分 分析 ①自定义一个模块common.js主要用于封装所有的请求函数 ②核心代码 function requestWithRetry(cmd, username, password, retryCount) {return new Promise((resolve, reject) > {uni.request({url: ip sys…...

数据结构-归并排序+计数排序

1.归并排序 基本思想&#xff1a; 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#xff0c;再使子序列段间有序。若将两个有序表合并成一个…...

Qml使用cpp文件的信号槽

文章目录 一、C文件Demo二、使用步骤1. 初始化C文件和QML文件&#xff0c;并建立信号槽2.在qml中调用 一、C文件Demo Q_INVOKABLE是一个Qt元对象系统中的宏&#xff0c;用于将C函数暴露给QML引擎。具体来说&#xff0c;它使得在QML代码中可以直接调用C类中被标记为Q_INVOKABLE的…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...