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

Java SpringBoot实现PDF转图片

不是单页图片,是多页PDF转成一张图片的逻辑。

我这里的场景是PDF转成图片之后返回给前端,前端再在图片上实现签字,并且可拖拽的逻辑,就是签订合同的场景。

但是这里只写后端多页PDF转图片的逻辑。

先说逻辑,后面直接上代码,大致分为以下几步:

  1. 读取PDF文件(我的代码里是将在线的URL转成InputStream了)
  2. 按PDF的页面循环计算图片的宽度和高度,其中宽度为PDF最宽的那一页的宽度(毕竟有的PDF比较骚,可能一页是横的,一页是竖的),高度为所有页面加起来的高度
  3. 用Graphics2D绘制
  4. 将Graphics2D的绘制结果输出为图片(只要有outputStream都好说,我这里是输出成base64给前端了,没什么存起来的必要)

好了,直接上代码:

先在pom.xml导入依赖:

		<!--   pdf读取     --><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.1</version></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>fontbox</artifactId><version>2.0.1</version></dependency>
	public String getSinglePicBase64Contracts(String fileUrl) throws IOException {byte[] pdfBytes = HttpUtil.createGet(fileUrl).execute().bodyBytes();InputStream inputStream = new ByteArrayInputStream(pdfBytes);PDDocument doc = PDDocument.load(inputStream);PDFRenderer pdfRenderer = new PDFRenderer(doc);List<BufferedImage> imageList = new ArrayList<>(doc.getNumberOfPages());int maxWidth = 0;int totalHeight = 0;for (int i = 0; i < doc.getNumberOfPages(); i++) {BufferedImage image = pdfRenderer.renderImage(i, 1.25f);imageList.add(image);if (image.getWidth() > maxWidth) {maxWidth = image.getWidth();}totalHeight += image.getHeight();}// 绘制结果BufferedImage result = new BufferedImage(maxWidth, totalHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = result.createGraphics();int nowHeight = 0;for (BufferedImage bufferedImage : imageList) {// padding 为页面的左边距int padding = (maxWidth - bufferedImage.getWidth()) / 2;g2d.drawImage(bufferedImage, padding, nowHeight, null);nowHeight += bufferedImage.getHeight();}ByteArrayOutputStream outputStream =  new ByteArrayOutputStream();ImageIO.write(result, "png", outputStream);String singlePicBase64 = "data:image/png;base64," + Base64.encodeBase64String(outputStream.toByteArray());return singlePicBase64;}

相关文章:

Java SpringBoot实现PDF转图片

不是单页图片&#xff0c;是多页PDF转成一张图片的逻辑。 我这里的场景是PDF转成图片之后返回给前端&#xff0c;前端再在图片上实现签字&#xff0c;并且可拖拽的逻辑&#xff0c;就是签订合同的场景。 但是这里只写后端多页PDF转图片的逻辑。 先说逻辑&#xff0c;后面直接…...

elasticsearch SQL:在Elasticsearch中启用和使用SQL功能

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…...

Java 并发编程:线程变量 ThreadLocal

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 029 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…...

【OpenHarmony4.1 之 U-Boot 2024.07源码深度解析】018 - init_sequence_f 各函数源码分析(二)

【OpenHarmony4.1 之 U-Boot 2024.07源码深度解析】018 - init_sequence_f 各函数源码分析(二) 一、arch_cpu_init二、arch_cpu_init系列文章汇总:《【OpenHarmony4.1 之 U-Boot 源码深度解析】000 - 文章链接汇总》 本文链接:《【OpenHarmony4.1 之 U-Boot 2024.07源码深度…...

LVS原理——详细介绍

目录 介绍 lvs简介 LVS作用 LVS 的优势与不足 LVS概念与相关术语 LVS的3种工作模式 LVS调度算法 LVS-dr模式 LVS-tun模式 ipvsadm工具使用 实验 nat模式集群部署 实验环境 webserver1配置 webserver2配置 lvs配置 dr模式集群部署 实验环境 router 效果呈现…...

MYSQL 5.7.36 等保 建设记录

文章目录 前言一、开启审计日志1.1 查看当前状态1.2 开启方式1.3 查看开启后状态 二、密码有效期2.1 查看当前状态2.2 开启方式2.3 查看开启后状态 三、密码复杂度3.1 查看当前状态3.2 开启方式3.3 查看开启后状态 四、连接控制4.1 查看当前状态4.2 开启方式4.3 查看开启后状态…...

fatal: unable to access ‘https://github.com/xxxxx

ubuntu中git克隆项目异常 git clone https://github.com/xxx Cloning into ‘xxx’… fatal: unable to access ‘https://github.com/xxx/xx.git/’: Could not resolve host: github.com 解决办法使用命令&#xff1a; git config --global http.proxy git config --global…...

从零开始的CPP(38)——递归与动态规划

leetcode46 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a; 输入&#…...

从战略到系统架构:信息系统设计的全面解析

在当今数字化时代&#xff0c;信息系统已成为企业运营、管理和创新的核心驱动力。信息系统设计的重要性不仅关乎企业的技术实现&#xff0c;更直接影响到企业的战略执行和市场竞争能力。本文将从战略视角出发&#xff0c;深入探讨信息系统设计的全过程&#xff0c;包括从战略制…...

GEE调用中国(China Land Cover Dataset,简称CLCD)1990-2022年30米分辨率的土地分类数据

博客推荐 GEE土地分类&#xff1a;中国30米年度土地覆盖产品annual China Land Cover Dataset, CLCD&#xff08;面积提取&#xff09;_30米土地利用数据gee-CSDN博客 简介 中国陆地覆盖数据集&#xff08;China Land Cover Dataset&#xff0c;简称CLCD&#xff09;是一个用…...

三十八、大数据技术之Kafka(1)

&#x1f33b;&#x1f33b; 目录 一、Kafka 概述1.1 定义1.2 消息队列1.2.1 消息队列内部实现原理1.2.2 传统消息队列的应用场景1.2.3 消息队列的两种模式 1.3 Kafka 基础架构 二、 Kafka 快速入门2.1 安装前的准备2.2 安装部署2.2.1 集群规划2.2.2 单节点或集群部署2.2.3 集群…...

将 Tcpdump 输出内容重定向到 Wireshark

在 Linux 系统中使用 Tcpdump 抓包后分析数据包不是很方便。 通常 Wireshark 比 tcpdump 更容易分析应用层协议。 一般的做法是在远程主机上先使用 tcpdump 抓取数据并写入文件&#xff0c;然后再将文件拷贝到本地工作站上用 Wireshark 分析。 还有一种更高效的方法&#xf…...

【Python蓝屏程序(管理员)】

说明&#xff1a;该程序为临摹(&#x1f600;)作品&#xff0c;源地址C蓝屏程序(非管理员) 我试图使用Python调用 NtRaiseHardError API &#xff0c;实现类似的蓝屏效果。可惜我发现Python在普通权限下&#xff0c;直接调用 NtRaiseHardError API 是不被允许的&#xff0c;因为…...

OpenGL ES->GLSurfaceView绘制图形的流程

自定义View代码 class MyGLSurfaceView(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs), GLSurfaceView.Renderer {var mProgrem 0init {// 设置 OpenGL ES 3.0 版本setEGLContextClientVersion(3)// 设置当前类为渲染器, 注册回调接口的实现类set…...

Linux OOM Killer详解

Linux OOM Killer详解 一、概述二、OOM Killer的技术原理1. 内存区域划分2. 内存耗尽与OOM Killer触发3. 选择被杀进程的策略4. 内存回收机制5. 内存分配策略 三、OOM Killer的工作机制1. 内存压力监测2. 触发条件3. 选择被杀进程4. 终止进程 四、实际场景举例场景一&#xff1…...

2024rk(案例二)

试题二(25分) 阅读以下关于数据库缓存的叙述,在答题纸上回答问题1至问题3。 【说明】 某大型电商平台建立了一个在线 B2B 商店系统,并在全国多地建设了货物仓储中心,通过提前备货的方式来提高货物的运送效率。但是在运营过程中,发现会出现很多跨仓储中心调货从而延误货物…...

小红书爆文秘籍:ChatGPT助你从0到1创造热门内容!

在小红书打造爆款文案的策略中&#xff0c;以下是一些调整和同义词替换的建议&#xff0c;以便达到文章去重的要求&#xff1a; 了解目标受众&#xff1a; 在撰写文案前&#xff0c;先深入分析目标读者的属性&#xff0c;如年龄层次、性别、爱好和购买行为。通过ChatGPT, 你能迅…...

django快速实现个人博客(附源码)

文章目录 一、工程目录组织结构二、模型及管理实现1、模型2、admin管理 三、博客展现实现1、视图实现2、模板实现 四、部署及效果五、源代码 Django作为一款成熟的Python Web开发框架提供了丰富的内置功能&#xff0c;如ORM&#xff08;对象关系映射&#xff09;、Admin管理界面…...

K8s部署篇之手动部署二进制高可用集群架构

一、系统环境初始化 一&#xff09;架构设计 所有节点都操作&#xff1a;3个master&#xff08;etcd集群三个节点&#xff09;和2个node 1、K8s服务调用如图 2、各组件说明 1、API Server 供Kubernetes API接口&#xff0c;主要处理 REST操作以及更新ETCD中的对象所有资源增删…...

【Unity/XLua】xlua自带教程示例分析(6)—— lua协程

文章目录 工具准备协程测试 工具准备 首先是工具脚本&#xff0c;一个Coroutine_Runner.cs和一个cs_coroutine.lua 前者定义了一个继承自Monobehavior的脚本组件&#xff0c;后者则使用lua去在Unity中实例化一个挂载该组件的GameObject&#xff0c;并将其设置为DontDestroyOn…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

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

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

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...