Java项目中整合多个pdf合并为一个pdf

一、Java项目中整合多个pdf合并为一个pdf

gitee笔记路径:https://gitee.com/happy_sad/drools

一、依赖导入

<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.6</version>
</dependency>
<dependency><groupId>org.kie</groupId><artifactId>kie-api</artifactId><version>7.6.0.Final</version>
</dependency>
<dependency><groupId>org.kie</groupId><artifactId>kie-internal</artifactId><version>7.6.0.Final</version>
</dependency>

二、设置端口

server.port=8082

三、设置已存在的多个pdf

注意:此次为模拟获取多个pdf,所以本人做两个pdf的合并实验,所以将两个pdf放入项目中的/resources/mergepdfs文件夹中,合并时遍历该文件夹下的所有文件,转换字节流

image-20240721160034444

四、controller

package com.jin.test.controller;import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;/*** @Package:com.jin.test.controller* @ClassName: MergepdfTestController* @Description: 项目中整合多个pdf合并为一个pdf* @Date: 2024/07/21 14:22* @Author: Jin*/
@Log4j2
@RestController
@RequestMapping("/mergepdf")
public class MergepdfTestController {@Autowiredprivate ResourceLoader resourceLoader;@RequestMapping("/download")public void downloadFile(HttpServletResponse response) throws Exception {List<byte[]> finalList = Collections.synchronizedList(new ArrayList<>());ArrayList<String> fileNames = new ArrayList<>();Resource folderResource = resourceLoader.getResource("classpath:" + "mergepdfs");if (folderResource.exists()) {try (Stream<Path> files = Files.list(Paths.get(folderResource.getURI()))) {files.forEach(filePath ->fileNames.add(filePath.toString()));}for (String fileNmae : fileNames) {File file = new File(fileNmae);FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream bos = new ByteArrayOutputStream();int byteContent;while ((byteContent = fis.read()) != -1) {bos.write(byteContent);}byte[] bytes = bos.toByteArray();finalList.add(bytes);}byte[] finalByte = this.mergepdf(finalList);ServletOutputStream outputStream = response.getOutputStream();outputStream.write(finalByte);outputStream.flush();} else {System.out.println("Folder not found: " + "mergepdfs");}}/*** pdf合并方法* @param bytes* @return* @throws Exception*/public byte[] mergepdf(List<byte[]> bytes) throws Exception {ByteArrayOutputStream bos = new ByteArrayOutputStream();Document document = new Document();PdfCopy copy = new PdfCopy(document, bos);document.open();for (byte[] bs : bytes) {PdfReader reader = new PdfReader(bs);int pageTotal = reader.getNumberOfPages();log.info("pdf的页码数是 ==>{}", pageTotal);for (int pageNo = 1; pageNo <= pageTotal; pageNo++) {document.newPage();PdfImportedPage page = copy.getImportedPage(reader, pageNo);copy.addPage(page);}reader.close();}document.close();byte[] pdfs = bos.toByteArray();bos.close();copy.close();return pdfs;}
}

五、测试结果

1、Apifox请求

http://localhost:8082/mergepdf/download

image-20240721155308587

2、例子1.pdf页数为26

image-20240721155044665

3、例子2.pdf页数为2

image-20240721155123050

4、合并后的pdf页数为28

image-20240721155155625

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3267438.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

ts 下使用 interactjs 的时候,事件类型该如何定义 InteractEvent

ts 下使用 interactjs 的时候&#xff0c;事件类型该如何定义 InteractEvent 一、问题 interactjs 是一个很好用的给元素添加拖动事件的插件&#xff0c;它可以实现如下的效果。 其官网是 https://interactjs.io/ vitetsvue3 项目中用到了 interactjs 这个库&#xff0c;但在…

事务、函数和索引

M y S Q L 事 务 什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09;&#xff0c;就是将一组SQL语句放在同一批次内去执行&#xff0c;如果一个SQL语句出错&#xff0c;则该批次内 的所有SQL都将被取消执行。 特点&#xff1a;一个事务中如果有一个数据库操作…

【Android】数据存储方案——文件存储、SharedPreferences、SQLite数据库用法总结

文章目录 文件存储存储到文件读取文件 SharedPreferences存储存储获取SharedPreferences对象Context 类的 getSharedPreferences() 方法Activity 类的 getPreferences() 方法PreferenceManager 类中的 getDefaultSharedPreferences() 方法 示例 读取记住密码的功能 SQLite数据库…

学习OCR具体使用

暂时找了三种&#xff0c;有一些问题待解决 Tesseract-OCR1. 安装库&#xff1a;2. 安装Tesseract-OCR&#xff1a;3. 安装中文语言包&#xff1a;4. Python代码&#xff1a;5. 运行结果 cnOCR1. 安装cnOCR&#xff1a;2. 使用cnOCR进行OCR&#xff1a;3. 运行结果 PaddleOCR1.…

vue 实战 区域内小组件元素拖拽 示例

<template><div><el-button type"primary" click"showDialog true">快捷布局</el-button><el-dialog title"快捷布局配置" :visible.sync"showDialog"><el-row :gutter"20"><el-co…

柯达sd卡数据丢失怎么办?分享有效数据恢复方法

随着科技的进步&#xff0c;数码相机已成为我们生活中不可或缺的一部分&#xff0c;而柯达作为摄影界的知名品牌&#xff0c;其相机及配件更是广受欢迎。然而&#xff0c;在日常使用中&#xff0c;难免会遇到数据丢失的情况&#xff0c;特别是SD卡中的数据丢失&#xff0c;常常…

大模型技术:发展历程、经典模型、微调与应用[更新中...]

文章目录 一、预训练语言模型发展历程二、经典的Pre-trained任务2.1 Masked Language Modeling2.2 Next Sentence Prediction 三、Task-specific Fine-tuning 任务3.1 Single-text Classification (单句分类)3.2 Sentence-pair Classification (句子匹配/成对分类)3.3 Span Tex…

Java3-final,singleInstance,enum

final可以用来修饰类、方法、变量 public static final -- 修饰常量 singleInstance-单例&#xff1b;一个类永远只存在一个对象 1、饿汉单例&#xff1b; --通过类获取单例对象的时候&#xff0c;对象已经提前做好了 --实现&#xff1a; 2、懒汉单例 --通过类获取单例对象…

C++第二十七弹---优先级队列的高级应用:结合仿函数优化性能

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1 priority_queue的介绍和使用 1.1 priority_queue的介绍 1.2 priority_queue的使用 2 仿函数的介绍和使用 2.1 仿函数的介绍 2.2 仿函数的…

Java的类加载机制

Java的类加载机制是指将类的字节码文件&#xff08;.class文件&#xff09;加载到JVM中并将其转换为Class对象的过程。这个过程由类加载器&#xff08;ClassLoader&#xff09;完成。Java的类加载机制具有动态性和灵活性&#xff0c;使得Java能够支持动态加载类、实现模块化开发…

C++ 八股(2)

1.函数调用的参数是以什么顺序压栈的&#xff0c;为什么&#xff1f; 从右向左压栈的。因为C, C支持可变参函数。 可变参函数就是参数个数可变的函数&#xff0c;如printf()就是可变参函数 void func(int a,...){} 2.有一个函数 在main函数中通过&#xff1a;string s fun…

数据库-触发器,存储过程

按照题目要求完成下列题目&#xff1a; 1.触发器 mysql> use mydb16_trigger; Database changed mysql> create table goods(-> gid char(8) primary key,-> name varchar(10),-> price decimal(8,2),-> num int); Query OK, 0 rows affected (0.01 sec)my…

工作流 Flowable

工作流包括业务流和审批流等业务流程。 在一个流程系统中&#xff0c;任务间往往存在复杂的依赖关系&#xff0c;为保证pipeline的正确执行&#xff0c;就是要解决各任务间依赖的问题&#xff0c;这样DAG结合拓扑排序是解决存在依赖关系的一类问题的利器。DAG ( Directed Acyc…

免费【2024】springboot 毕业生学历证明系统

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

Android AI应用开发:移动检测

基于Google ML模型的Android移动物体检测应用——检测、跟踪视频中的物体 A. 项目描述 ML Kit物体检测器可以对视频流进行操作&#xff0c;能够检测视频中的物体并在连续视频帧中跟踪该物体。 相机捕捉视频时&#xff0c;检测到移动物体并为其生成一个边界框&#xff0c;并分…

微信小程序-本地部署(前端)

遇到问题&#xff1a;因为是游客模式所以不能修改appID. 参考链接&#xff1a;微信开发者工具如何从游客模式切换为开发者模式&#xff1f;_微信开发者工具如何修改游客模式-CSDN博客 其余参考&#xff1a;Ego微商项目部署&#xff08;小程序项目&#xff09;&#xff08;全网…

Xstate inspect状态图的使用 和 原理

状态图的好处之一是&#xff0c;在将状态图组合在一起的过程中&#xff0c;您可以探索流程中所有可能的状态。这种探索将帮助您避免代码中的错误和错误&#xff0c;因为您更有可能涵盖所有可能发生的情况。 因为状态图是可执行的&#xff0c;所以它们既可以表现为图&#xff0…

K8s集群prometheus镜像配置非root用户执行导致监控页面targets无相关node信息监控

【问题描述】 K8s集群prometheus镜像配置非root用户执行导致监控页面targets无相关node信息监控 【问题记录】 在k8s容器集群来部署prometheus服务,实现对node节点的监控,但发现部署了prometheus后页面targets没有显示node信息,配置检查也是正确的 排查prometheus日志发现…

速递!OpenAI 凌晨发布 SearchGPT 进军 AI 搜索,正式与 Google、Perplexity 竞争

&#x1f431; 个人主页&#xff1a;TechCodeAI启航&#xff0c;公众号&#xff1a;TechCodeAI &#x1f64b;‍♂️ 作者简介&#xff1a;2020参加工作&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab; 优质专…

数据分析或处理中关于坐标系的一些事

通过对本文的阅读&#xff0c;你将获取坐标系的一些基础知识&#xff0c;以及学会如何使用pyproj实现地理数据的投影与转换。更重要的是&#xff0c;作为一个开发者&#xff0c;面对地理坐标系的图层数据&#xff0c;需要进行面积计算、距离量测、规则分块等需求时&#xff0c;…