2017-06-20 83 views
3

我想生成iText的7 PDF格式,但有些錯誤發生在我們身上:Itext7生成PDF格式爲Exception「PDF格式的間接對象屬於其他PDF文檔。將對象複製到當前的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<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 
    } 


} 

我唯一的樣式代碼itext7:

private PdfFont bfChinese = null; 

將在調用服務構造函數時初始化爲:

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

我已經嘗試將我的字體設置爲靜態,但不起作用。

這是地方拋出異常:

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); 
     } 
    } 

這意味着我有兩個不同的文件,但我不知道我何時創建另一個文件。 在此先感謝您的建議。

回答

3

我自己也經歷過同樣的問題(我花了幾個小時才發現我做錯了什麼)。事實證明,您只能爲一個文檔使用特定的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); 
     ... 
    } 
} 

ThisGoesWrong創建了一個正確的PDF你第一次叫createPdf(),但它表明,當你把它稱爲第二次你有例外。

,我發現這解決了這個問題:

class ThisWorksOK { 

    public ThisWorksOK() { 
    } 

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

我不知道這是否是一個bug(它肯定感覺就像一個錯誤),所以我將創造iText的集團內部票。

+0

*我不知道這是否是一個bug(它肯定感覺就像一個臭蟲)* - 如果字體最終可以作爲文檔中使用的某些字體程序的字形子集嵌入,因此將其視爲鏈接到文檔是有意義的。否則,您必須收集每個文檔使用的字形的數據。當然可以爭辯說,類名「PdfFont」是錯誤的,它應該是「PdfDocumentFont」。 – mkl

+0

謝謝lottttttttttt。有用 。 –

+0

@ Cheng.T左邊有一個複選標記,右邊是我的答案的零分。請檢查該標記,因爲我的答案解決了您的問題。 –

1

爲了提高性能與您應該重用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); 
    ... 
} 
+0

是的,使字體私人,我已經解決了這個,謝謝你的任何方式。 –