使用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使用上述方法即可解决该问题。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

世界上那些最容易的事情中,拖延时间最不费力。

使用itextpdf解决PDF合并的问题

相关文章:

你感兴趣的文章:

标签云: