Itext7生成带有异常的pdf"Pdf间接对象属于其他PDF文档.将对象复制到当前的pdf文档."

Che*_*g.T 8 java pdf itext7

我想用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]
Run Code Online (Sandbox Code Playgroud)

我的生成代码:

public void generatePDF(CreditQueryData creditQueryData, Map<String, UserCreditContentView> contentViewMap, List<PackageCreditContentView> 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
    }


}
Run Code Online (Sandbox Code Playgroud)

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

 private PdfFont bfChinese = null;
Run Code Online (Sandbox Code Playgroud)

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

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

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

这是抛出异常的地方:

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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

Bru*_*gie 18

我自己也经历过同样的问题(我花了几个小时才发现我做错了什么).事实证明,您只能将一个特定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);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

该类ThisGoesWrong在您第一次调用时会创建一个正确的PDF createPdf(),但它会显示您第二次调用它时的异常.

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

class ThisWorksOK {

    public ThisWorksOK() {
    }

    public void createPdf() {
        ...
        PdfFont font = PdfFontFactory.createFont(...);
        Paragraph p = new Paragraph("test").setFont(font);
        document.add(p);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @bruno-lowagie,听到你超然地讨论你自己的创作,很有趣,就好像指的是一个搬出去的儿子一样。不管怎样,三年后的今天,我遇到了这条消息……这是否意味着我们决定这是一个功能,而不是一个错误?不管怎样,谢谢你的指导。我会花上一辈子和一天的时间才能弄清楚。 (2认同)

Pav*_*lay 5

为了提高性能,您应该重用 FontProgram:

private FontProgram bfChinese = null;

public GeneratePDFService() {
    String PdfFontPath = EnvironmentUtils.getClasspathFilePath("font/MSYH.TTF");
    try {
        bfChinese =  FontProgramFactory.createFont(PdfFontPath);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

进而:

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