我有以下代码
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。
答案 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 answer到How to insert an PDPage within another PDPage with pdfbox解释了如何将模板页面导入为表单xobject并将其放在当前PDFBox 2.0.0开发SNAPSHOT中的某个目标页面上。对于当前版本的1.8.X,也应该有类似的东西。