Itext7生成带有exception的pdf“Pdf间接对象属于其他PDF文档。 将对象复制到当前的pdf文档。“

我想用itext 7生成一个pdf,但是我们遇到了一些错误:

com.itextpdf.kernel.PdfException: Pdf indirect object belongs to other PDF document. Copy object to current pdf document. at com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:195) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:185) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:115) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:187) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:115) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:187) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:115) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfWriter.writeToBody(PdfWriter.java:383) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfWriter.flushObject(PdfWriter.java:289) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfDocument.flushObject(PdfDocument.java:1572) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfObject.flush(PdfObject.java:159) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfObject.flush(PdfObject.java:127) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfObjectWrapper.flush(PdfObjectWrapper.java:94) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfPage.flush(PdfPage.java:495) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfPage.flush(PdfPage.java:454) ~[kernel-7.0.2.jar:na] at com.itextpdf.kernel.pdf.PdfDocument.close(PdfDocument.java:785) ~[kernel-7.0.2.jar:na] at com.itextpdf.layout.Document.close(Document.java:120) ~[layout-7.0.2.jar:na] at com.xcz.afbp.thirdparty.service.impl.GeneratePDFService.generatePDF(GeneratePDFService.java:160) ~[classes/:na] 

我的生成代码:

 public void generatePDF(CreditQueryData creditQueryData, Map contentViewMap, List needRetrievedCreditContentList, File pdfFile, BigDecimal score) throws Exception { if (!pdfFile.exists()) { boolean x = pdfFile.createNewFile(); if (!x) { LOG.error("生成文件出错" + pdfFile.getPath()); return; } } PdfDocument pdf = new PdfDocument(new PdfWriter(new FileOutputStream(pdfFile))); Document document = new Document(pdf, PageSize.A4); document.setRenderer(new DocumentRenderer(document)); pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new WatermarkingEventHandler()); try { //operate code just add tableA tableB tableC... } catch (Exception e) { LOG.info(); } finally { document.close(); //exception throws here } } 

我在itext7中唯一的样式代码:

  private PdfFont bfChinese = null; 

将调用服务构造函数中的init:

  public GeneratePDFService() { String PdfFontPath = EnvironmentUtils.getClasspathFilePath("font/MSYH.TTF"); try { bfChinese = PdfFontFactory.createFont(PdfFontPath, "Identity-H", true); } catch (Exception e) { e.printStackTrace(); } } 

我已经尝试将我的字体设置为静态 ,但不起作用。

这是抛出exception的地方:

 private void write(PdfIndirectReference indirectReference) { if (document != null && !indirectReference.getDocument().equals(document)) { throw new PdfException(PdfException.PdfIndirectObjectBelongsToOtherPdfDocument); } if (indirectReference.getRefersTo() == null) { write(PdfNull.PDF_NULL); } else if (indirectReference.getGenNumber() == 0) { writeInteger(indirectReference.getObjNumber()). writeBytes(endIndirectWithZeroGenNr); } else { writeInteger(indirectReference.getObjNumber()). writeSpace(). writeInteger(indirectReference.getGenNumber()). writeBytes(endIndirect); } } 

这意味着我有两个不同的文件,但我不知道什么时候我创建了另一个文件。 提前感谢您的建议。

我自己也经历过同样的问题(我花了几个小时才发现我做错了什么)。 事实certificate,您只能将一个特定的PdfFont实例用于一个文档。 只要您使用PdfFont实例,它就会链接到该文档,您无法再在其他文档中使用它。

例如:

 class ThisGoesWrong { protected PdfFont font; public ThisGoesWrong() { font = PdfFontFactory.createFont(...); } public void createPdf() { ... Paragraph p = new Paragraph("test").setFont(font); document.add(p); ... } } 

第一次调用createPdf()ThisGoesWrong类会创建一个正确的PDF,但它会显示您第二次调用它时的exception。

我发现这解决了这个问题:

 class ThisWorksOK { public ThisWorksOK() { } public void createPdf() { ... PdfFont font = PdfFontFactory.createFont(...); Paragraph p = new Paragraph("test").setFont(font); document.add(p); ... } } 

我不知道这是不是一个bug(当然感觉就像一个bug),所以我将在iText Group创建一张内部门票。

要提高性能,您应该重复使用FontProgram:

 private FontProgram bfChinese = null; public GeneratePDFService() { String PdfFontPath = EnvironmentUtils.getClasspathFilePath("font/MSYH.TTF"); try { bfChinese = FontProgramFactory.createFont(PdfFontPath); } catch (Exception e) { e.printStackTrace(); } } 

接着:

 public void createPdf() { ... PdfFont font = PdfFontFactory.createFont(bfChinese, "Identity-H", true); Paragraph p = new Paragraph("test").setFont(font); document.add(p); ... } 

这就是我解决这个问题的方法。

  1. 创建了一个DocumentUtil类
  2. 添加静态方法

     public class DocumentUtils { public static PdfFont setFont() throws Exception { return PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN); } } 
  3. 使用如下字体:

     PDfFont font = DocumentUtil.setFont();