java html转word、pdf(包含图片)
html转word
maven依赖
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.14</version>
</dependency>
<dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.11.3</version>
</dependency>
核心代码
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Entities;
import org.jsoup.select.Elements;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;import org.jsoup.nodes.Document;
import sun.misc.BASE64Encoder;@RestController
public class WordController {@GetMapping("/")public String html2doc(HttpServletResponse response) throws IOException {byte b[] = getHtml().getBytes();ByteArrayInputStream bais = new ByteArrayInputStream(b);POIFSFileSystem poifs = new POIFSFileSystem();DirectoryEntry directory = poifs.getRoot();DocumentEntry documentEntry = directory.createDocument("WordDocument", bais);//输出文件String name = "test";name = java.net.URLEncoder.encode(name, "UTF-8");response.reset();response.setHeader("Content-Disposition","attachment;filename=" +new String((name + ".doc").getBytes(),"utf-8"));response.setContentType("application/msword;charset=utf-8");OutputStream ostream = response.getOutputStream();//输出到本地文件的话,new一个文件流poifs.writeFilesystem(ostream);bais.close();ostream.close();return null;}public String getHtml() {String content = "<p><img src=\"https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png\" alt=\"\" width=\"233\" height=\"233\" /></p>";Document doc = Jsoup.parse(content);Elements img = doc.select("img");img.forEach(p -> {p.attr("src", "data:image/jpeg;base64," + ImageToBase64ByOnline(p.attr("src")));});doc.head().append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></meta>");// jsoup标准化标签,生成闭合标签doc.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml);doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml);return doc.html();}/*** 在线图片转换成base64字符串** @param imgURL 图片线上路径* @return*/public static String ImageToBase64ByOnline(String imgURL) {ByteArrayOutputStream data = new ByteArrayOutputStream();try {// 创建URLURL url = new URL(imgURL);byte[] by = new byte[1024];// 创建链接HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(5000);InputStream is = conn.getInputStream();// 将内容读取内存中int len = -1;while ((len = is.read(by)) != -1) {data.write(by, 0, len);}// 关闭流is.close();} catch (IOException e) {e.printStackTrace();}// 对字节数组Base64编码BASE64Encoder encoder = new BASE64Encoder();return encoder.encode(data.toByteArray());}
}
html转pdf
maven依赖
<dependency><groupId>org.xhtmlrenderer</groupId><artifactId>core-renderer</artifactId><version>R8</version>
</dependency>
<dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.11.3</version>
</dependency>
核心代码
import com.lowagie.text.DocumentException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Entities;
import org.jsoup.select.Elements;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;import org.jsoup.nodes.Document;
import sun.misc.BASE64Encoder;@RestController
public class PdfController {@GetMapping("/")public String html2pdf(HttpServletResponse response) throws DocumentException, IOException {ITextRenderer renderer = new ITextRenderer();//图片base64支持,把图片转换为itext自己的图片对象renderer.getSharedContext().setReplacedElementFactory(new Base64ImgReplacedElementFactory());renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);renderer.setDocumentFromString(getHtml());ITextFontResolver fontResolver = renderer.getFontResolver();renderer.layout();String fileName = "test.pdf";fileName = java.net.URLEncoder.encode(fileName, "UTF-8");response.reset();response.setCharacterEncoding("UTF-8");response.setContentType("application/pdf");//打开浏览器窗口预览文件response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes(), "iso8859-1"));OutputStream ostream = response.getOutputStream();renderer.createPDF(ostream);ostream.close();return null;}public String getHtml() {String content = "<p><img src=\"https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png\" alt=\"\" width=\"233\" height=\"233\" /></p>";Document doc = Jsoup.parse(content);Elements img = doc.select("img");img.forEach(p -> {p.attr("src", "data:image/jpeg;base64," + ImageToBase64ByOnline(p.attr("src")));});doc.head().append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></meta>");// jsoup标准化标签,生成闭合标签doc.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml);doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml);return doc.html();}/*** 在线图片转换成base64字符串** @param imgURL 图片线上路径* @return*/public static String ImageToBase64ByOnline(String imgURL) {ByteArrayOutputStream data = new ByteArrayOutputStream();try {// 创建URLURL url = new URL(imgURL);byte[] by = new byte[1024];// 创建链接HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(5000);InputStream is = conn.getInputStream();// 将内容读取内存中int len = -1;while ((len = is.read(by)) != -1) {data.write(by, 0, len);}// 关闭流is.close();} catch (IOException e) {e.printStackTrace();}// 对字节数组Base64编码BASE64Encoder encoder = new BASE64Encoder();return encoder.encode(data.toByteArray());}
}
Base64ImgReplacedElementFactory类
import java.io.IOException;import org.w3c.dom.Element;
import org.xhtmlrenderer.extend.FSImage;
import org.xhtmlrenderer.extend.ReplacedElement;
import org.xhtmlrenderer.extend.ReplacedElementFactory;
import org.xhtmlrenderer.extend.UserAgentCallback;
import org.xhtmlrenderer.layout.LayoutContext;
import org.xhtmlrenderer.pdf.ITextFSImage;
import org.xhtmlrenderer.pdf.ITextImageElement;
import org.xhtmlrenderer.render.BlockBox;
import org.xhtmlrenderer.simple.extend.FormSubmissionListener;import com.lowagie.text.BadElementException;
import com.lowagie.text.Image;
import com.lowagie.text.pdf.codec.Base64;
/*** 图片base64支持,把图片转换为itext自己的图片对象**/
public class Base64ImgReplacedElementFactory implements ReplacedElementFactory {/*** 实现createReplacedElement 替换html中的Img标签** @param c 上下文* @param box 盒子* @param uac 回调* @param cssWidth css宽* @param cssHeight css高* @return ReplacedElement*/@Overridepublic ReplacedElement createReplacedElement(LayoutContext c, BlockBox box, UserAgentCallback uac,int cssWidth, int cssHeight) {Element e = box.getElement();if (e == null) {return null;}String nodeName = e.getNodeName();// 找到img标签if (nodeName.equals("img")) {String attribute = e.getAttribute("src");FSImage fsImage;try {// 生成itext图像fsImage = buildImage(attribute, uac);} catch (BadElementException e1) {fsImage = null;} catch (IOException e1) {fsImage = null;}if (fsImage != null) {// 对图像进行缩放if (cssWidth != -1 || cssHeight != -1) {fsImage.scale(cssWidth, cssHeight);}return new ITextImageElement(fsImage);}}return null;}/*** 编解码base64并生成itext图像*/protected FSImage buildImage(String srcAttr, UserAgentCallback uac) throws IOException,BadElementException {FSImage fiImg=null;if (srcAttr.toLowerCase().startsWith("data:image/")) {String base64Code= srcAttr.substring(srcAttr.indexOf("base64,") + "base64,".length(),srcAttr.length());// 解码byte[] decodedBytes = Base64.decode(base64Code);fiImg= new ITextFSImage(Image.getInstance(decodedBytes));} else {fiImg= uac.getImageResource(srcAttr).getImage();}return fiImg;}@Overridepublic void reset() {}@Overridepublic void remove(Element arg0) {}@Overridepublic void setFormSubmissionListener(FormSubmissionListener arg0) {}}相关文章:
java html转word、pdf(包含图片)
html转word maven依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.14</version> </dependency> <dependency><groupId>org.jsoup</groupId><artifactId>…...
不容易解的题10.10
5.最长回文子串 5. 最长回文子串 - 力扣(LeetCode)https://leetcode.cn/problems/longest-palindromic-substring/?envTypelist&envIdZCa7r67M给一个字符串,让我们找最长回文子串 这题不用说,回文子串那一定是连续的&#…...
淘宝天猫店铺所有商品数据接口,淘宝API接口
获取淘宝店铺所有商品数据接口的步骤如下: 获取授权:使用 OAuth 2.0 协议对应用进行授权,以便能够访问店铺的商品信息。获取店铺信息:使用淘宝 API 的 taobao.shop.get 接口,传入店铺的 user_id 参数,获取…...
Prometheus和grafana安装配置手册
1.简介 本文档为prometheus和grafana安装配置手册,prometheus和grafana的内容、和操作过程,详细介绍了服务监控配置、dashboard配置、告警配置等操作。 2.部署说明 Prometheus基于Golang编写(需要安装),编译后的软件…...
从零开始探索C语言(十一)----共用体和位域
文章目录 1. 共用体1.1 定义共用体1.2 访问共用体成员 2. 位域2.1 位域声明2.2 位域的定义和位域变量的说明2.3 位域的使用2.4 位域小结 1. 共用体 共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体&#…...
【数据结构】算法的时间复杂度
🦄个人主页:修修修也 🎏所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.算法时间复杂度定义 二.大O阶渐近表示法 🎏大O阶渐近表示法的定义 🎏推导大O阶方法 三.常见的时间复杂度 📌常数阶 &#x…...
Qt作业五
1、思维导图 https://www.zhixi.com/view/9e899ee0 2、作业 #include <iostream>using namespace std;class Animal { private:string name; public:Animal(){}Animal(string n):name(n){}virtual void perform()0; };class Lion:public Animal { public:void perform…...
【面试】pc寄存器题
目录 1.使用pc寄存器存储字节码指令地址有什么作用?(为什么使用pc寄存器记录当前线程的执行地址?)2.pc寄存器为什么被设定为线程私有的? 1.使用pc寄存器存储字节码指令地址有什么作用?(为什么使…...
ARM按键中断实验
设置按键中断,按键1按下,LED亮,再按一次,灭 按键2按下,蜂鸣器响。再按一次,不响 按键3按下,风扇转,再按一次,风扇停 src/do_irq.c #include "key_it.h" ex…...
C#的值类型和引用类型
不得不说c#的类型系统设计有点意思,不同的编程语言对于类型的设计各有取舍。 值类型: 当我们将一个int类型的值赋值到另一个int类型的值时,它实际上是创建了一个完全不同的副本。换句话说,如果你改变了其中某一个的值࿰…...
YOLOv7改进:极简的神经网络模型 VanillaNet---VanillaBlock助力检测,实现暴力涨点 | 华为诺亚2023
💡💡💡本文属于原创独家改进:极简模块VanillaBlock,以极简主义的设计为理念,网络中仅仅包含最简单的卷积计算,去掉了残差和注意力模块,二次创新引入到YOLOv7中取得了不俗的效果。 极简模块VanillaBlock | 亲测在多个数据集实现涨点; 收录: YOLOv7高阶自研专…...
对验证码的识别爆破
声明:该系列文章首发于公众号:Y1X1n安全,转载请注明出处!本公众号所分享内容仅用于每一个爱好者之间的技术讨论及教育目的,所有渗透及工具的使用都需获取授权,禁止用于违法途径,否则需自行承担&…...
LeetCode【15】三数之和
题目: 解析: 参考:https://zhuanlan.zhihu.com/p/111715985 代码: public static List<List<Integer>> threeSum(int[] nums) {// 先排序Arrays.sort(nums);List<List<Integer>> result new ArrayLis…...
Gossip协议是什么
Gossip协议是什么 Gossip protocol 也叫 Epidemic Protocol (流行病协议), 是基于流行病传播方式的节点或者进程之间信息交换的协议, 也被叫做流言算法, 八卦算法、疫情传播算法等等. 说到 Gossip 协议, 就不得不提著名的六度分隔理论. 简单地说, 你和任何一个陌生人之间所间…...
【java学习】this关键字(27)
文章目录 1. this是什么?2. this的作用 1. this是什么? 在 java 中,this关键字比较难理解,它的作用和其词义很接近。 ①它在方法内部使用,即这个方法所属对象的引用; ②它在构造器内部使用,表示…...
27、元组
区分: 数组:纯粹 一个[]中的数据类型都是一致的 元组:不纯粹 一个[]中可能有不同类型的数据项 意义 当赋值或访问一个已知索引的元素时,可以得到正确的类型 let miao: [string, number] [cat, 18]; miao[0] cat miao[1] 18…...
1km分辨率逐月降雨量和最高温度数据集(1901-2022)--数据处理
1km分辨率逐月降雨量和最高温度数据集(1901-2022)的下载可以参考我的另外一篇博客: 这里的温度和降雨数据集都是NC格式的,需要将其处理为tif格式,我采用的处理软件是MATLAB。 本篇博客以处理温度数据为例,…...
docker入门加实战—docker常见命令
docker入门加实战—docker常见命令 在介绍命令之前,先用一副图形象的展示一下docker的命令: 常见命令 docker的常见命令和文档地址如下表: 命令说明文档地址docker pull拉取镜像docker pulldocker push推送镜像到DockerRegistrydocker pus…...
【C/C++】使用 g++ 编译器编译 C++ 程序的完全指南
本文介绍了 g 编译器的使用方法和常见参数解释,帮助您编译和构建 C 程序。 引言 在 C 程序开发中,选择一个合适的编译器是至关重要的。g 是 GNU 编译器集合(GCC)中的 C 编译器,提供了丰富的功能和选项,帮…...
ARM中断实验
设置按键中断,按键1按下,LED亮,再按一次,灭 按键2按下,蜂鸣器响。再按一次,不响 按键3按下,风扇转,再按一次,风扇停 main.c #include "uart1.h" #include …...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
