当前位置: 首页 > 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 …...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

C#中用于控制自定义特性(Attribute)

我们来详细解释一下 [AttributeUsage(AttributeTargets.Class, AllowMultiple false, Inherited false)] 这个 C# 属性。 在 C# 中&#xff0c;Attribute&#xff08;特性&#xff09;是一种用于向程序元素&#xff08;如类、方法、属性等&#xff09;添加元数据的机制。Attr…...