使用itextpdf解决PDF合并的问题

作者:MissEel 时间:2023-09-21 04:47:16 

itextpdf解决PDF合并的问题

本文章是我在项目开发过程中解决了一个关于PDF显示的需求而记录的。

需求是这样的,需要将两个PDF进行合并,一个PDF是根据数据库的信息在在后台形成的(实际不存在的PDF),另一个是磁盘保存的PDF文件(这个PDF文件后期会变成从云端获取)。

作为一个Java菜鸟,这个问题解决了数天,还是在leader的指导下解决的。在这里做一下关键代码的记录。

项目主要包含了以下关键词:(我不做详解了,主要是用了这些)

- Spring MVC、Spring、Hibernate

- Maven

- Java

- itextpdf

- MySQL

- JavaWeb相关

首先是itextpdf的依赖


<dependency>
   <groupId>com.itextpdf</groupId>
   <artifactId>itextpdf</artifactId>
   <version>5.5.10</version>
</dependency>

如何在后台生成一个PDF

这个问题,百度上有很多解决方案,因为我需要将这个生成的PDF和已存在的PDF拼接,于是尝试了多种方案,决定将这个以文档的形式,将这个文档转为字节数组,然后用itextpdf将流读取到PDF中。

生成PDF的部分代码:


import java.io.ByteArrayOutputStream;
import com.model.User;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
public class ReportKit {
    public static byte[] createReport(User user) throws Exception {
              ByteArrayOutputStream ba = new ByteArrayOutputStream();
              Document doc = new Document();//创建一个document对象
              PdfWriter writer = PdfWriter.getInstance(doc, ba);//这个PdfWriter会一直往文档里写内容。
             doc.open();//开启文档
             BaseFont bfChinese = BaseFont.createFont("c://windows//fonts//msyh.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
             com.itextpdf.text.Font FontChinese18 = new com.itextpdf.text.Font(bfChinese, 18, com.itextpdf.text.Font.BOLD);
             com.itextpdf.text.Font FontChinese12 = new com.itextpdf.text.Font(bfChinese, 12, com.itextpdf.text.Font.NORMAL);
             com.itextpdf.text.Font FontChinese11 = new com.itextpdf.text.Font(bfChinese, 11, com.itextpdf.text.Font.ITALIC);
             Font fontChinese =  new  Font(bfChinese  ,  12 , Font.NORMAL, BaseColor.BLACK);
             Paragraph pf = new Paragraph("");
             //加入空行
             Paragraph blankRow1 = new Paragraph(24f," ",FontChinese18);
             doc.add(blankRow1);
             //table2
             PdfPTable table25 = new PdfPTable(2);
             //设置每列宽度比例
             int width21[] = {2,98};
             table25.setWidths(width21);
             table25.getDefaultCell().setBorder(0);
             PdfPCell cell25 = new PdfPCell(new Paragraph("这是一个报告",FontChinese18));
             cell25.setBorder(0);
             table25.addCell("");
             table25.addCell(cell25);
             doc.add(table25);
             Paragraph blankRow3 = new Paragraph(18f, "Report ", FontChinese11);
             blankRow3.setAlignment(PdfContentByte.ALIGN_RIGHT);
             doc.add(blankRow3);        
             BaseColor lightGrey = new BaseColor(0xCC,0xCC,0xCC);
             PdfPTable table8 = new PdfPTable(6);
           //设置table的宽度为100%
           table8.setWidthPercentage(100);
           //设置不同列的宽度
           float[] columnWidths = {1.6f, 1.6f, 1.6f, 1.6f, 1.6f, 1.6f};
           table8.setWidths(columnWidths);
             PdfPCell cell1 = new PdfPCell(new Paragraph("用户名",FontChinese12));
           PdfPCell cell2 = new PdfPCell(new Paragraph("出生日期",FontChinese12));
           PdfPCell cell3 = new PdfPCell(new Paragraph("性别",FontChinese12));
           PdfPCell cell4 = new PdfPCell(new Paragraph("身高",FontChinese12));
           PdfPCell cell5 = new PdfPCell(new Paragraph("体重",FontChinese12));
           PdfPCell cell6 = new PdfPCell(new Paragraph("地区",FontChinese12));
           PdfPCell cell7 = new PdfPCell(new Paragraph(user.getAccessname(),FontChinese12));
           PdfPCell cell8 = new PdfPCell(new Paragraph(user.getBirthday(),FontChinese12));
           PdfPCell cell9 = new PdfPCell(new Paragraph(sex,FontChinese12));
           PdfPCell cell10 = new PdfPCell(new Paragraph(String.valueOf(user.getHeight()),FontChinese12));
           PdfPCell cell11 = new PdfPCell(new Paragraph(String.valueOf(user.getWeight()),FontChinese12));
           PdfPCell cell12 = new PdfPCell(new Paragraph(user.getArea_name(),FontChinese12));
           //表格高度
           cell1.setFixedHeight(30);
           cell2.setFixedHeight(30);
           cell3.setFixedHeight(30);
           cell4.setFixedHeight(30);
           cell5.setFixedHeight(30);
           cell6.setFixedHeight(30);
           cell7.setFixedHeight(30);
           cell8.setFixedHeight(30);
           cell9.setFixedHeight(30);
           cell10.setFixedHeight(30);
           cell11.setFixedHeight(30);
           cell12.setFixedHeight(30);
           //水平居中
          cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell3.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell4.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell5.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell6.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell7.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell8.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell9.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell10.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell11.setHorizontalAlignment(Element.ALIGN_CENTER);
           cell12.setHorizontalAlignment(Element.ALIGN_CENTER);
           //垂直居中
           cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell3.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell4.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell5.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell6.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell7.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell8.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell9.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell10.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell11.setVerticalAlignment(Element.ALIGN_MIDDLE);
           cell12.setVerticalAlignment(Element.ALIGN_MIDDLE);
           //边框颜色
           cell1.setBorderColor(lightGrey);
           cell2.setBorderColor(lightGrey);
           cell3.setBorderColor(lightGrey);
           cell4.setBorderColor(lightGrey);
           cell5.setBorderColor(lightGrey);
           cell6.setBorderColor(lightGrey);
           cell7.setBorderColor(lightGrey);
           cell8.setBorderColor(lightGrey);
           cell9.setBorderColor(lightGrey);
           cell10.setBorderColor(lightGrey);
           cell11.setBorderColor(lightGrey);
           cell12.setBorderColor(lightGrey);
           table8.addCell(cell1);
           table8.addCell(cell2);
           table8.addCell(cell3);
           table8.addCell(cell4);
           table8.addCell(cell5);
           table8.addCell(cell6);
           table8.addCell(cell7);
           table8.addCell(cell8);
           table8.addCell(cell9);
           table8.addCell(cell10);
           table8.addCell(cell11);
           table8.addCell(cell12);        
           doc.add(table8);
           doc.close();//(有开启文档,就要记得关闭文档)
           writer.close();
           byte[] bytes = ba.toByteArray();          
           return bytes;
    }
}

用document来编辑文档,真的蛮恶心的,费时费力,排版也不好调,如果能有更加好用的方式,希望大家能告诉我。

到这里,调用这个方法,就可以获得这个文档的字节数组了。

接下来开始拼接PDF。因为是结合前端页面实现的。因此这个方法是我在controller完成的。


//注意这里的produces,“application/pdf”,正是因为设置了这个,使得整个方法会将文档以PDF的格式返回到页面。
@RequestMapping(value = "/newPdf/{report_name}", produces = "application/pdf;charset=UTF-8")
   public void updateReport(Model model, @PathVariable String report_name, HttpServletRequest request,
           HttpServletResponse response,HttpSession session) {
       try {
           User user = (User) session.getAttribute("user");
           //这是用户登录后保存到session里的用户信息(可以用别的对象来替代这个)
           if(user==null){
               return ;
           }
           PdfReader reader1 =null;
           try {
               // 调用刚刚写的生成PDF的方法,将这个字节数组获取。
               byte[] pdfUserByte=ReportKit.createReport(user);
               if(pdfUserByte==null||pdfUserByte.length==0){
                   return;
               }
               //用pdfReader来读取字节数组,这里将文档信息读入
                reader1 = new PdfReader(pdfUserByte);
           } catch (Exception e) {
               System.out.println(e.getMessage());
               return ;
           }
           if(reader1==null) return;
           //第二个PDF的读取
           PdfReader reader2;
           // 报告的PDF
           reader2 = new PdfReader("C:\\Users\\Administrator\\Desktop\\report.pdf");
           Document document = new Document();
           PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
           document.open();
           PdfContentByte cb = writer.getDirectContent();
           int totalPages = 0;
           totalPages += reader1.getNumberOfPages();
           totalPages += reader2.getNumberOfPages();
           java.util.List<PdfReader> readers = new ArrayList<PdfReader>();
           readers.add(reader1);
           readers.add(reader2);
           int pageOfCurrentReaderPDF = 0;
           Iterator<PdfReader> iteratorPDFReader = readers.iterator();
           // Loop through the PDF files and add to the output.
           while (iteratorPDFReader.hasNext()) {
               PdfReader pdfReader = iteratorPDFReader.next();
               // Create a new page in the target for each source page.
               while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
                   document.newPage();//创建新的一页
                   pageOfCurrentReaderPDF++;
                   PdfImportedPage page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
                   cb.addTemplate(page, 0, 0);
               }
               pageOfCurrentReaderPDF = 0;
           }
           document.close();
           writer.close();
       } catch (IOException | DocumentException e) {
           e.printStackTrace();
       }
   }

关于如何在页面预览这个PDF,我用了object标签来获取。

jsp上的部分片段


   <div class="pdf" id="pdf" ><!-- pdf -->
   <object type="application/pdf" data="http://localhost:8080/project/newPdf/${report.report_name}" id="review" style="width:1100px; height:1000px; margin-top:25px; margin-left:50px" >
   </object>
   </div>

标签很好的实现了PDF预览的功能,如果是URL的PDF,data直接输入URL,就能将PDF在页面预览,感觉蛮好用的。

iText 合并PDF文件报错

在使用iText操作PDF进行合并的时候报错:

com.lowagie.text.exceptions.BadPasswordException: PdfReader not opened with owner password


public static PdfReader unlockPdf(PdfReader pdfReader) {
    if (pdfReader == null) {
     return pdfReader;
    }
    try {
     java.lang.reflect.Field f = pdfReader.getClass().getDeclaredField("encrypted");
     f.setAccessible(true);
     f.set(pdfReader, false);
    } catch (Exception e) {
      // ignore
    }
    return pdfReader;
   }

对reader使用上述方法即可解决该问题。

来源:https://blog.csdn.net/MissEel/article/details/75220571

标签:itextpdf,PDF,合并
0
投稿

猜你喜欢

  • java操作solr实现查询功能的实例

    2023-08-04 10:41:34
  • Java虚拟机内存结构及编码实战分享

    2023-11-29 13:47:47
  • 解决异常FileNotFoundException:class path resource找不到资源文件的问题

    2021-12-26 18:24:14
  • 新手学习Java对Redis简单操作

    2023-09-10 05:05:41
  • Android手势识别功能

    2022-07-23 22:04:26
  • VC实现屏幕截词功能的方法详解

    2022-08-05 07:22:18
  • Java实体类不要使用基本类型的知识点总结

    2023-02-21 10:04:49
  • SpringBoot如何实现Tomcat自动配置

    2022-04-28 02:44:10
  • Android RecyclerView详解及简单实例

    2023-03-06 21:31:29
  • Spring Security认证的完整流程记录

    2021-12-15 13:04:03
  • java——多线程基础

    2021-08-08 04:14:25
  • C#实现一阶卡尔曼滤波算法的示例代码

    2022-12-23 05:28:45
  • Android实现自定义圆形进度条

    2022-10-28 04:55:22
  • Spring Cloud Gateway入门解读

    2023-03-14 12:01:00
  • React Native与Android 原生通信的方法

    2021-08-11 19:02:56
  • IDEA安装阿里巴巴编码规范插件的两种方式详解(在线安装和离线安装)

    2022-07-23 19:18:54
  • C#实现图书管理系统

    2023-03-24 04:30:35
  • Java跨域问题的处理详解

    2021-07-05 12:55:18
  • IntelliJ IDEA2020.1版本更新pom文件自动导包的方法

    2023-01-13 17:44:01
  • Java包装类的概述与应用

    2022-03-14 07:50:43
  • asp之家 软件编程 m.aspxhome.com