Itext7 生成带有异常 "Pdf indirect object belongs to other PDF document. Copy object to current pdf document." 的 pdf
Itext7 generate pdf with Exception "Pdf indirect object belongs to other PDF document. Copy object to current pdf document."
我想用 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<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();
}
}
我试过将我的字体设置为 static,但不起作用。
这是抛出异常的地方:
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);
}
}
这意味着我有两个不同的文档,但我不知道何时创建了另一个文档。
在此先感谢您的建议。
我自己也遇到过同样的问题(我花了几个小时才发现我做错了什么)。事实证明,您只能对一个文档使用特定的 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);
...
}
}
class ThisGoesWrong
会在您第一次调用 createPdf()
时创建正确的 PDF,但它会显示您在第二次调用时遇到的异常。
我发现这解决了问题:
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);
...
}
这就是我解决问题的方法。
- 创建了一个 DocumentUtil class
添加静态方法
public class DocumentUtils {
public static PdfFont setFont() throws Exception {
return PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN);
}
}
使用如下字体:
PDfFont font = DocumentUtil.setFont();
我想用 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<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();
}
}
我试过将我的字体设置为 static,但不起作用。
这是抛出异常的地方:
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);
}
}
这意味着我有两个不同的文档,但我不知道何时创建了另一个文档。 在此先感谢您的建议。
我自己也遇到过同样的问题(我花了几个小时才发现我做错了什么)。事实证明,您只能对一个文档使用特定的 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);
...
}
}
class ThisGoesWrong
会在您第一次调用 createPdf()
时创建正确的 PDF,但它会显示您在第二次调用时遇到的异常。
我发现这解决了问题:
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);
...
}
这就是我解决问题的方法。
- 创建了一个 DocumentUtil class
添加静态方法
public class DocumentUtils { public static PdfFont setFont() throws Exception { return PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN); } }
使用如下字体:
PDfFont font = DocumentUtil.setFont();