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

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. 最长回文子串 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/longest-palindromic-substring/?envTypelist&envIdZCa7r67M给一个字符串&#xff0c;让我们找最长回文子串 这题不用说&#xff0c;回文子串那一定是连续的&#…...

淘宝天猫店铺所有商品数据接口,淘宝API接口

获取淘宝店铺所有商品数据接口的步骤如下&#xff1a; 获取授权&#xff1a;使用 OAuth 2.0 协议对应用进行授权&#xff0c;以便能够访问店铺的商品信息。获取店铺信息&#xff1a;使用淘宝 API 的 taobao.shop.get 接口&#xff0c;传入店铺的 user_id 参数&#xff0c;获取…...

Prometheus和grafana安装配置手册

1.简介 本文档为prometheus和grafana安装配置手册&#xff0c;prometheus和grafana的内容、和操作过程&#xff0c;详细介绍了服务监控配置、dashboard配置、告警配置等操作。 2.部署说明 Prometheus基于Golang编写&#xff08;需要安装&#xff09;&#xff0c;编译后的软件…...

从零开始探索C语言(十一)----共用体和位域

文章目录 1. 共用体1.1 定义共用体1.2 访问共用体成员 2. 位域2.1 位域声明2.2 位域的定义和位域变量的说明2.3 位域的使用2.4 位域小结 1. 共用体 共用体是一种特殊的数据类型&#xff0c;允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体&#…...

【数据结构】算法的时间复杂度

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.算法时间复杂度定义 二.大O阶渐近表示法 &#x1f38f;大O阶渐近表示法的定义 &#x1f38f;推导大O阶方法 三.常见的时间复杂度 &#x1f4cc;常数阶 &#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寄存器存储字节码指令地址有什么作用&#xff1f;&#xff08;为什么使用pc寄存器记录当前线程的执行地址&#xff1f;&#xff09;2.pc寄存器为什么被设定为线程私有的&#xff1f; 1.使用pc寄存器存储字节码指令地址有什么作用&#xff1f;&#xff08;为什么使…...

ARM按键中断实验

设置按键中断&#xff0c;按键1按下&#xff0c;LED亮&#xff0c;再按一次&#xff0c;灭 按键2按下&#xff0c;蜂鸣器响。再按一次&#xff0c;不响 按键3按下&#xff0c;风扇转&#xff0c;再按一次&#xff0c;风扇停 src/do_irq.c #include "key_it.h" ex…...

C#的值类型和引用类型

不得不说c#的类型系统设计有点意思&#xff0c;不同的编程语言对于类型的设计各有取舍。 值类型&#xff1a; 当我们将一个int类型的值赋值到另一个int类型的值时&#xff0c;它实际上是创建了一个完全不同的副本。换句话说&#xff0c;如果你改变了其中某一个的值&#xff0…...

YOLOv7改进:极简的神经网络模型 VanillaNet---VanillaBlock助力检测,实现暴力涨点 | 华为诺亚2023

💡💡💡本文属于原创独家改进:极简模块VanillaBlock,以极简主义的设计为理念,网络中仅仅包含最简单的卷积计算,去掉了残差和注意力模块,二次创新引入到YOLOv7中取得了不俗的效果。 极简模块VanillaBlock | 亲测在多个数据集实现涨点; 收录: YOLOv7高阶自研专…...

对验证码的识别爆破

声明&#xff1a;该系列文章首发于公众号&#xff1a;Y1X1n安全&#xff0c;转载请注明出处&#xff01;本公众号所分享内容仅用于每一个爱好者之间的技术讨论及教育目的&#xff0c;所有渗透及工具的使用都需获取授权&#xff0c;禁止用于违法途径&#xff0c;否则需自行承担&…...

LeetCode【15】三数之和

题目&#xff1a; 解析&#xff1a; 参考&#xff1a;https://zhuanlan.zhihu.com/p/111715985 代码&#xff1a; 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是什么&#xff1f;2. this的作用 1. this是什么&#xff1f; 在 java 中&#xff0c;this关键字比较难理解&#xff0c;它的作用和其词义很接近。 ①它在方法内部使用&#xff0c;即这个方法所属对象的引用&#xff1b; ②它在构造器内部使用&#xff0c;表示…...

27、元组

区分&#xff1a; 数组&#xff1a;纯粹 一个[]中的数据类型都是一致的 元组&#xff1a;不纯粹 一个[]中可能有不同类型的数据项 意义 当赋值或访问一个已知索引的元素时&#xff0c;可以得到正确的类型 let miao: [string, number] [cat, 18]; miao[0] cat miao[1] 18…...

1km分辨率逐月降雨量和最高温度数据集(1901-2022)--数据处理

1km分辨率逐月降雨量和最高温度数据集&#xff08;1901-2022&#xff09;的下载可以参考我的另外一篇博客&#xff1a; 这里的温度和降雨数据集都是NC格式的&#xff0c;需要将其处理为tif格式&#xff0c;我采用的处理软件是MATLAB。 本篇博客以处理温度数据为例&#xff0c…...

docker入门加实战—docker常见命令

docker入门加实战—docker常见命令 在介绍命令之前&#xff0c;先用一副图形象的展示一下docker的命令&#xff1a; 常见命令 docker的常见命令和文档地址如下表&#xff1a; 命令说明文档地址docker pull拉取镜像docker pulldocker push推送镜像到DockerRegistrydocker pus…...

【C/C++】使用 g++ 编译器编译 C++ 程序的完全指南

本文介绍了 g 编译器的使用方法和常见参数解释&#xff0c;帮助您编译和构建 C 程序。 引言 在 C 程序开发中&#xff0c;选择一个合适的编译器是至关重要的。g 是 GNU 编译器集合&#xff08;GCC&#xff09;中的 C 编译器&#xff0c;提供了丰富的功能和选项&#xff0c;帮…...

ARM中断实验

设置按键中断&#xff0c;按键1按下&#xff0c;LED亮&#xff0c;再按一次&#xff0c;灭 按键2按下&#xff0c;蜂鸣器响。再按一次&#xff0c;不响 按键3按下&#xff0c;风扇转&#xff0c;再按一次&#xff0c;风扇停 main.c #include "uart1.h" #include …...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...