当前位置:   article > 正文

【itext7】使用itext7将多个PDF文件、图片合并成一个PDF文件,图片旋转、图片缩放-支持Android_itext7-core

itext7-core

这篇文章,主要介绍使用itext7将多个PDF文件、图片合并成一个PDF文件,图片旋转、图片缩放。 

目录

一、itext7合并PDF

1.1、引入依赖

1.2、合并PDF介绍

1.3、采用字节数组方式读取PDF文件

1.4、合并多个PDF文件

1.5、合并图片到PDF文件

1.6、旋转图片

1.7、完整案例代码

(1)PDFUtil工具类

(2)测试类代码

(3)合并效果


一、itext7合并PDF

1.1、引入依赖

我这里使用的是itext-core7.1.16版本,只需要引入一个itext-core依赖即可,因为这个依赖里面已经给我们引入了itext所需要的依赖。

  1. <!-- 引入 itext7-core 依赖 -->
  2. <dependency>
  3. <groupId>com.itextpdf</groupId>
  4. <artifactId>itext7-core</artifactId>
  5. <version>7.1.16</version>
  6. <type>pom</type>
  7. </dependency>

1.2、合并PDF介绍

最简单的合并方式,那就是读取两个PDF文件,然后将其合并成一个新的PDF文件,保存到服务器上面之后,在将这个新的PDF文件和下一个待合并的PDF文件进行合并,以此类推,最终可以得到一个完整的PDF文件,但是这种方式缺点在于,每一次合并之后,都需要新生成一个PDF文件,并且下一次合并之后,还要再读取这个PDF文件,这就会导致多次读取文件的过程,效率不是很理想。

这篇文章,我主要是将PDF作为字节数组读取到内存里面,然后在内存中合并两个PDF的字节数据,这样可以减少读取和生成PDF文件的次数,执行效率方面也就会更加好一些了,合并两个PDF字节数组的方法如下所示:

  1. /**
  2. * 基于内存中的字节数组进行PDF文档的合并
  3. * @param firstPdf 第一个PDF文档
  4. * @param secondPdf 第二个PDF文档
  5. */
  6. private static byte[] mergePdfBytes(byte[] firstPdf, byte[] secondPdf) throws IOException {
  7. if (firstPdf != null && secondPdf != null) {
  8. // 创建字节数组,基于内存进行合并
  9. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  10. PdfDocument destDoc = new PdfDocument(new PdfWriter(baos));
  11. // 合并的pdf文件对象
  12. PdfDocument firstDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(firstPdf)));
  13. PdfDocument secondDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(secondPdf)));
  14. // 合并对象
  15. PdfMerger merger = new PdfMerger(destDoc);
  16. merger.merge(firstDoc, 1, firstDoc.getNumberOfPages());
  17. merger.merge(secondDoc, 1, secondDoc.getNumberOfPages());
  18. // 关闭文档流
  19. merger.close();
  20. firstDoc.close();
  21. secondDoc.close();
  22. destDoc.close();
  23. return baos.toByteArray();
  24. }
  25. return null;
  26. }

1.3、采用字节数组方式读取PDF文件

合并PDF文件的时候,有些PDF文件可能是网络上的,也有些是本地磁盘上的,所以这里需要做下判断,如果是网络上的PDF文件,则需要首先访问网络,再将其保存到字节数组里面,如果是本地磁盘文件,则需要读取本地文件。

  1. /**
  2. * 将pdf文档转换成字节数组
  3. * @param pdf PDF文档路径
  4. * @return 返回对应PDF文档的字节数组
  5. */
  6. private static byte[] getPdfBytes(String pdf) throws Exception {
  7. ByteArrayOutputStream out = new ByteArrayOutputStream();
  8. InputStream is;
  9. if (pdf.startsWith("http://") || pdf.startsWith("https://")) {
  10. is = new URL(pdf).openStream();
  11. } else {
  12. is = new FileInputStream(pdf);
  13. }
  14. byte[] data = new byte[2048];
  15. int len;
  16. while ((len = is.read(data)) != -1) {
  17. out.write(data, 0, len);
  18. }
  19. return out.toByteArray();
  20. }

1.4、合并多个PDF文件

合并PDF时候,直接传递需要合并的PDF文件路径就可以啦,调用下面方法,就可以完成合并。

  1. /**
  2. * 将给定List集合中的pdf文档,按照顺序依次合并,生成最终的目标PDF文档
  3. * @param pdfPathLists 待合并的PDF文档路径集合,可以是本地PDF文档,也可以是网络上的PDF文档
  4. * @param destPath 目标合并生成的PDF文档路径
  5. */
  6. public static boolean mergeMultiplePdfs(List<String> pdfPathLists, String destPath) {
  7. try {
  8. int size = pdfPathLists.size();
  9. byte[] pdfData = getPdfBytes(pdfPathLists.get(0));
  10. for (int i = 1; i < size; i++) {
  11. pdfData = mergePdfBytes(pdfData, getPdfBytes(pdfPathLists.get(i)));
  12. }
  13. if (pdfData != null) {
  14. FileOutputStream fis = new FileOutputStream(destPath);
  15. fis.write(pdfData);
  16. fis.close();
  17. }
  18. return true;
  19. } catch (Exception e) {
  20. logger.error("合并PDF异常:", e);
  21. }
  22. return false;
  23. }

1.5、合并图片到PDF文件

如何将图片也一起合并到PDF文件里面呢???这里我是将图片直接添加到PDF文件的空白页面中实现的,一张图片占据一个页面,当然,你也可以设置显示在相同页面,超过之后页面高度之后,图片会自动显示到下一个页面。

  1. /**
  2. * 将给定集合中的图片合并到一个pdf文档里面
  3. * @param imagePathList 图片路径集合
  4. * @param destPath 合并之后的PDF文档
  5. */
  6. public static boolean mergeImagesToPdf(List<String> imagePathList, String destPath) {
  7. try {
  8. PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destPath));
  9. Document document = new Document(pdfDocument);
  10. if (imagePathList != null && imagePathList.size() > 0) {
  11. int size = imagePathList.size();
  12. for (int i = 0; i < size; i++) {
  13. String imgPath = imagePathList.get(i);
  14. ImageData imageData;
  15. if (imgPath.startsWith("http://") || imgPath.startsWith("https://")) {
  16. imageData = ImageDataFactory.create(new URL(imgPath));
  17. } else {
  18. imageData = ImageDataFactory.create(imgPath);
  19. }
  20. Image image = new Image(imageData);
  21. /*
  22. 设置旋转的弧度值,默认是逆时针旋转的。
  23. 弧度、角度换算公式:
  24. 1° = PI / 180°
  25. 1 rad = 180° / PI
  26. */
  27. image.setRotationAngle(- Math.PI / 2); // 顺时针旋转90°
  28. // 设置图片自动缩放,即:图片宽高自适应
  29. image.setAutoScale(true);
  30. document.add(image);
  31. if (i != size - 1) {
  32. // 最后一页不需要新增空白页
  33. document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
  34. }
  35. }
  36. }
  37. pdfDocument.close();
  38. return true;
  39. } catch (Exception e) {
  40. logger.error("合并图片到PDF异常:", e);
  41. }
  42. return false;
  43. }

1.6、旋转图片

在某些需求下,你可以想某个图片竖向摆放、某些图片横向摆放,那么这个时候,就可以调用itext7中【Image】图片对象的【setRotationAngle()】方法,对其进行旋转,需要注意的是:setRotationAngle方法设置的旋转弧度,而不是旋转角度,并且它是逆时针旋转的。弧度和角度之间有一个转换公式,如下所示:

1.7、完整案例代码

(1)PDFUtil工具类
  1. package com.gitcode.itext.util;
  2. import com.itextpdf.io.image.ImageData;
  3. import com.itextpdf.io.image.ImageDataFactory;
  4. import com.itextpdf.kernel.pdf.PdfDocument;
  5. import com.itextpdf.kernel.pdf.PdfReader;
  6. import com.itextpdf.kernel.pdf.PdfWriter;
  7. import com.itextpdf.kernel.utils.PdfMerger;
  8. import com.itextpdf.layout.Document;
  9. import com.itextpdf.layout.element.AreaBreak;
  10. import com.itextpdf.layout.element.Image;
  11. import com.itextpdf.layout.property.AreaBreakType;
  12. import org.slf4j.Logger;
  13. import org.slf4j.LoggerFactory;
  14. import java.io.*;
  15. import java.net.URL;
  16. import java.util.List;
  17. /**
  18. * @version 1.0.0
  19. * @Date: 2023/10/04 10:07
  20. * @Author ZhuYouBin
  21. * @Description: PDF工具类【基于 itext7 组件实现】
  22. */
  23. public class PDFUtil {
  24. private static final Logger logger = LoggerFactory.getLogger(PDFUtil.class);
  25. /**
  26. * 将给定List集合中的pdf文档,按照顺序依次合并,生成最终的目标PDF文档
  27. * @param pdfPathLists 待合并的PDF文档路径集合,可以是本地PDF文档,也可以是网络上的PDF文档
  28. * @param destPath 目标合并生成的PDF文档路径
  29. */
  30. public static boolean mergeMultiplePdfs(List<String> pdfPathLists, String destPath) {
  31. try {
  32. int size = pdfPathLists.size();
  33. byte[] pdfData = getPdfBytes(pdfPathLists.get(0));
  34. for (int i = 1; i < size; i++) {
  35. pdfData = mergePdfBytes(pdfData, getPdfBytes(pdfPathLists.get(i)));
  36. }
  37. if (pdfData != null) {
  38. FileOutputStream fis = new FileOutputStream(destPath);
  39. fis.write(pdfData);
  40. fis.close();
  41. }
  42. return true;
  43. } catch (Exception e) {
  44. logger.error("合并PDF异常:", e);
  45. }
  46. return false;
  47. }
  48. /**
  49. * 将给定集合中的图片合并到一个pdf文档里面
  50. * @param imagePathList 图片路径集合
  51. * @param destPath 合并之后的PDF文档
  52. */
  53. public static boolean mergeImagesToPdf(List<String> imagePathList, String destPath) {
  54. try {
  55. PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destPath));
  56. Document document = new Document(pdfDocument);
  57. if (imagePathList != null && imagePathList.size() > 0) {
  58. int size = imagePathList.size();
  59. for (int i = 0; i < size; i++) {
  60. String imgPath = imagePathList.get(i);
  61. ImageData imageData;
  62. if (imgPath.startsWith("http://") || imgPath.startsWith("https://")) {
  63. imageData = ImageDataFactory.create(new URL(imgPath));
  64. } else {
  65. imageData = ImageDataFactory.create(imgPath);
  66. }
  67. Image image = new Image(imageData);
  68. /*
  69. 设置旋转的弧度值,默认是逆时针旋转的。
  70. 弧度、角度换算公式:
  71. 1° = PI / 180°
  72. 1 rad = 180° / PI
  73. */
  74. image.setRotationAngle(- Math.PI / 2); // 顺时针旋转90°
  75. // 设置图片自动缩放,即:图片宽高自适应
  76. image.setAutoScale(true);
  77. document.add(image);
  78. if (i != size - 1) {
  79. // 最后一页不需要新增空白页
  80. document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
  81. }
  82. }
  83. }
  84. pdfDocument.close();
  85. return true;
  86. } catch (Exception e) {
  87. logger.error("合并图片到PDF异常:", e);
  88. }
  89. return false;
  90. }
  91. /**
  92. * 基于内存中的字节数组进行PDF文档的合并
  93. * @param firstPdf 第一个PDF文档
  94. * @param secondPdf 第二个PDF文档
  95. */
  96. private static byte[] mergePdfBytes(byte[] firstPdf, byte[] secondPdf) throws IOException {
  97. if (firstPdf != null && secondPdf != null) {
  98. // 创建字节数组,基于内存进行合并
  99. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  100. PdfDocument destDoc = new PdfDocument(new PdfWriter(baos));
  101. // 合并的pdf文件对象
  102. PdfDocument firstDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(firstPdf)));
  103. PdfDocument secondDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(secondPdf)));
  104. // 合并对象
  105. PdfMerger merger = new PdfMerger(destDoc);
  106. merger.merge(firstDoc, 1, firstDoc.getNumberOfPages());
  107. merger.merge(secondDoc, 1, secondDoc.getNumberOfPages());
  108. // 关闭文档流
  109. merger.close();
  110. firstDoc.close();
  111. secondDoc.close();
  112. destDoc.close();
  113. return baos.toByteArray();
  114. }
  115. return null;
  116. }
  117. /**
  118. * 将pdf文档转换成字节数组
  119. * @param pdf PDF文档路径
  120. * @return 返回对应PDF文档的字节数组
  121. */
  122. private static byte[] getPdfBytes(String pdf) throws Exception {
  123. ByteArrayOutputStream out = new ByteArrayOutputStream();
  124. InputStream is;
  125. if (pdf.startsWith("http://") || pdf.startsWith("https://")) {
  126. is = new URL(pdf).openStream();
  127. } else {
  128. is = new FileInputStream(pdf);
  129. }
  130. byte[] data = new byte[2048];
  131. int len;
  132. while ((len = is.read(data)) != -1) {
  133. out.write(data, 0, len);
  134. }
  135. return out.toByteArray();
  136. }
  137. }
(2)测试类代码
  1. package com.gitcode.itext;
  2. import com.gitcode.itext.util.PDFUtil;
  3. import java.io.FileNotFoundException;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. /**
  7. * @version 1.0.0
  8. * @Date: 2023/10/4 11:12
  9. * @Author ZhuYouBin
  10. * @Description:
  11. */
  12. public class ImageDemo {
  13. public static void main(String[] args) throws FileNotFoundException {
  14. // 图片合并之后生成的PDF路径
  15. String imagePath = "F:\\pdf-demo\\imagePath.pdf";
  16. List<String> imageList = new ArrayList<>();
  17. imageList.add("F:\\pdf-demo\\01.jpg");
  18. imageList.add("F:\\pdf-demo\\02.jpg");
  19. // 先合并图片
  20. PDFUtil.mergeImagesToPdf(imageList, imagePath);
  21. // 在合并PDF
  22. String destPath = "F:\\pdf-demo\\merge.pdf";
  23. List<String> pdfPath = new ArrayList<>();
  24. pdfPath.add("F:\\pdf-demo\\demo01.pdf");
  25. pdfPath.add("F:\\pdf-demo\\demo02.pdf");
  26. pdfPath.add(imagePath);
  27. PDFUtil.mergeMultiplePdfs(pdfPath, destPath);
  28. }
  29. }
(3)合并效果

到此,itext7合并PDF文件就介绍完啦。

综上,这篇文章结束了,主要介绍使用itext7将多个PDF文件、图片合并成一个PDF文件,图片旋转、图片缩放。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号