软件编程
位置:首页>> 软件编程>> java编程>> 使用itextpdf解决PDF合并的问题

使用itextpdf解决PDF合并的问题

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

标签:itextpdf,PDF,合并

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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com