[英]PDFbox loading large files
我正在尝试使用 PDFBox 将 pdf 文件的第一页转换为图像。 当我加载大型 pdf 文件时,出现异常。
代码:
PDDocument doc;
try {
InputStream input = new URL("http://www.jewishfederations.org/local_includes/downloads/39497.pdf").openStream();
doc = PDDocument.load(input);
PDPage firstPage = (PDPage) doc.getDocumentCatalog().getAllPages().get(0);
BufferedImage image =firstPage.convertToImage();
File outputfile = new File("image2.png");
ImageIO.write(image, "png", outputfile);
input.close();
doc.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
例外:
org.apache.pdfbox.pdfparser.BaseParser parseCOSStream
WARNING: Specified stream length 72435 is wrong. Fall back to reading stream until 'endstream'.
org.apache.pdfbox.exceptions.WrappedIOException: Could not push back 72435 bytes in order to reparse stream. Try increasing push back buffer using system property org.apache.pdfbox.baseParser.pushBackSize
at org.apache.pdfbox.pdfparser.BaseParser.parseCOSStream(BaseParser.java:554)
at org.apache.pdfbox.pdfparser.PDFParser.parseObject(PDFParser.java:605)
at org.apache.pdfbox.pdfparser.PDFParser.parse(PDFParser.java:194)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1219)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1186)
at Worker.main(Worker.java:27)
Caused by: java.io.IOException: Push back buffer is full
at java.io.PushbackInputStream.unread(Unknown Source)
at org.apache.pdfbox.io.PushBackInputStream.unread(PushBackInputStream.java:144)
at org.apache.pdfbox.io.PushBackInputStream.unread(PushBackInputStream.java:133)
at org.apache.pdfbox.pdfparser.BaseParser.parseCOSStream(BaseParser.java:550)
... 5 more
1.8.* PDFBox 版本的替代解决方案是使用非顺序解析器。 在这种情况下,代码不会是
doc = PDDocument.load(input);
但
doc = PDDocument.loadNonSeq(input, null);
该解析器(将是即将到来的 2.0 版本中唯一的解析器)与推回缓冲区的大小无关。
首先,找到当前缓冲区大小:
System.out.println(System.getProperty("org.apache.pdfbox.baseParser.pushBackSize"));
现在你有了一个基线,完全按照它的建议去做。 使用此将缓冲区大小增加到您刚刚打印出来的大小:
System.setProperty("org.apache.pdfbox.baseParser.pushBackSize", "<buffer size>");
继续增加缓冲区大小,直到它起作用为止。 希望你不会耗尽内存,如果你确实增加了堆。
这就是您在运行时设置系统属性的方式。 您也可以将其作为参数传递,但我发现在 main 开头附近设置可以解决问题,并使未来的开发人员更容易维护项目。
无论出于何种原因,对于大文件,您没有足够大的缓冲区来加载页面。 也许页面在渲染成图像之前或期间被加载到缓冲区中。 我的猜测是 PDF 中的 DPI 非常高,无法放入缓冲区。
我有一个类似的问题,我认为这与基于错误的大型 pdf 文件有关,但事实证明并非如此。 原来是一个损坏的pdf文件。
对于我们的用例,我们有一个 pdf 模板文件(我们以编程方式填充其表单值)作为我们项目中的资源,该文件已融入我们的战争。
我看到的异常供参考: org.apache.pdfbox.exceptions.WrappedIOException: Could not push back 480478 bytes in order to reparse stream. Try increasing push back buffer using system property org.apache.pdfbox.baseParser.pushBackSize
org.apache.pdfbox.exceptions.WrappedIOException: Could not push back 480478 bytes in order to reparse stream. Try increasing push back buffer using system property org.apache.pdfbox.baseParser.pushBackSize
。 我们添加了属性,然后再次运行,我们遇到了不同的问题。
下一个堆栈跟踪指出“无法读取字体 TimesNewRoman,Bold 的嵌入 TTF”。 我们花了一段时间,但是在爆发战争并尝试在战争中打开 pdf 文件后,我们注意到它已损坏,但源中的 pdf 文件未损坏,可以毫无问题地打开。
我们问题的根本原因是我们在 pom 中为我们的资源文件夹添加了“过滤”。 我们这样做是为了我们可以使用一些反射来获取健康检查页面中的一些值,但这破坏了 pdf 文件,我们从以下参考资料中发现: https : //bitbucket.org/petermr/xhtml2stm/issues/ 12/pdf-files-are-being-corrupted-at-some
以下是我们设置的过滤示例:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
我们的解决方案是从我们的 pom 中删除它,并重新设计我们获取健康页面信息的方式。
在 2.0.* 版本中,像这样打开 PDF:
PDDocument doc = PDDocument.load(file, MemoryUsageSetting.setupTempFileOnly());
这将设置缓冲内存使用以仅使用大小不受限制的临时文件(无主内存)。
祝你好运
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.