PdfBox无法导入页面

时间:2014-04-08 07:04:59

标签: pdfbox

我有以下代码

0. templatePage = (PDPage) PDDocument.load(file).getDocumentCatalog().getAllPages().get(0);
1. ...
2. document.importPage(templatePage); //first page
3. ... //draw stuff
4. document.importPage(templatePage); //next page
5. ...

如果在第3行,我只画了一些东西,那么一切正常。但是,如果我画了很多东西,那么我得到:

Index: 12, Size: 0. Stacktrace follows:
java.lang.IndexOutOfBoundsException: Index: 12, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at org.apache.pdfbox.io.RandomAccessBuffer.seek(RandomAccessBuffer.java:84)
at org.apache.pdfbox.io.RandomAccessFileInputStream.read(RandomAccessFileInputStream.java:96)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at org.apache.pdfbox.pdmodel.PDDocument.importPage(PDDocument.java:654)
at xxx.PdfReport.breakPage(PdfReport.java:145)
at xxx.PdfReport.print(PdfReport.java:84)

上述代码在95%的情况下起作用,只有当页面真的满时才会出现问题。

如果在第2行。&我用

 document.addPage(new PDPage());

然后它工作正常。但目标是使用模板pdf。

2 个答案:

答案 0 :(得分:0)

黑客解决方案是:

每次使用前加载模板。确保模板文档不是GCd。 然后它会工作。

如果有人有正式解决方案,请告诉我。

答案 1 :(得分:0)

主要问题

主要问题是您从文件中加载PDDocument

PDDocument.load(file)

从中提取PDPage个对象,

....getDocumentCatalog().getAllPages().get(0)

但是在使用页面时不再保留PDDocument实例。

document.importPage(templatePage)

因此,您允许垃圾收集声明PDDocument实例从PDPage实例下拉地毯:

PDPage对象保存所有页面内容的所有信息,但只包含一些必须在document.importPage调用期间解析的对象标识符;如果源PDDocument同时已经完成(由于未被引用,因此最终被垃圾收集处理),它们将无法再解析。

这种症状可能有所不同,在我的测试中,我没有例外,而是一个严重的日志输出

No Kids found in getAllKids(). Probably a malformed pdf.

并且未导入任何页面或导入的页面缺少某些资源,例如嵌入字体。

(顺便说一下,我实际上更喜欢在这里获得一个例外,因为没有它,代码假定成功导入了页面

解决方案

只要您使用PDDocument实例,就抓住它:

0. PDDocument sourceDocument = PDDocument.load(file);
   templatePage = (PDPage) sourceDocument .getDocumentCatalog().getAllPages().get(0);
1. ...
2. document.importPage(templatePage); //first page
3. ... //draw stuff
4. document.importPage(templatePage); //next page
5. ...
   sourceDocument.close();

最终的sourceDocument.close调用会在您选择的时间释放资源,而不是在垃圾收集管理的时间。

其他优化

导入相同模板PDPage两次的问题是,相同的内容流在结果文件中是两次,也可能是其资源。根据所讨论页面的性质,这可能意味着相当多的开销。您可以通过将模板页面作为表单xobject导入一次并在目标文档中的任意数量的页面上包含对此xobject的引用来解决此开销。

This answerHow to insert an PDPage within another PDPage with pdfbox解释了如何将模板页面导入为表单xobject并将其放在当前PDFBox 2.0.0开发SNAPSHOT中的某个目标页面上。对于当前版本的1.8.X,也应该有类似的东西。