【问题标题】:PDFBox PDFMergerUtility: how do I tell which sources failed?PDFBox PDFMergerUtility:我如何判断哪些来源失败了?
【发布时间】:2016-02-12 23:12:00
【问题描述】:

所以,我正在这样做:

PDFMergerUtility mergePdf = new PDFMergerUtility();

for (int i = 0; i < filePaths.size(); i++) 
    mergePdf.addSource(filePaths.get(i));

mergePdf.setDestinationFileName(tempFile.getAbsolutePath()); 
mergePdf.mergeDocuments();

在无法解析的 PDF 上引发异常之前,这非常有效(损坏的 PDF 或 PDFBox 无法处理的东西)。这种情况并不经常发生。

我希望能够知道它失败的来源,在随后的合并中排除它们,并告诉用户哪些文档失败了。

这个可以吗?

更新:

这是我的例外:

java.io.IOException: Error: Expected a long type at offset 591535, instead got 'E^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^UZí^KÄ@©¢^X<8d>G §ÑE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^TQE^T<84>f<96><8a>'
    at org.apache.pdfbox.pdfparser.BaseParser.readLong(BaseParser.java:1695)
    at org.apache.pdfbox.pdfparser.BaseParser.readObjectNumber(BaseParser.java:1623)
    at org.apache.pdfbox.pdfparser.PDFParser.parseObject(PDFParser.java:614)
    at org.apache.pdfbox.pdfparser.PDFParser.parse(PDFParser.java:203)
    at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1220)
    at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1187)
    at org.apache.pdfbox.util.PDFMergerUtility.mergeDocuments(PDFMergerUtility.java:237)
    at org.apache.pdfbox.util.PDFMergerUtility.mergeDocuments(PDFMergerUtility.java:194)
    at myapp.util.DocumentImage.combinePDFs(DocumentImage.java:289)
    at myapp.webapp.download.DownloadLatestForCLO.generate(DownloadLatestForCLO.java:73)
    at myapp.webapp.download.DownloadLatestForCLO.getFileSize(DownloadLatestForCLO.java:64)
    at myapp.webapp.download.DownloadServlet.handleRequest(DownloadServlet.java:58)
    at myapp.webapp.download.DownloadServlet.doGet(DownloadServlet.java:32)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:200)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

【问题讨论】:

  • 根据堆栈跟踪,异常发生在PDDocument.load。只需自己加载这些文档。
  • 你用的是什么版本?当前版本是 1.8.11 或 2.0 RC3。如果您使用的是 1.8.11,请使用 mergeDocumentsNonSeq() 方法。

标签: java exception pdfbox unparseable


【解决方案1】:

幸运的是,PDFBox 是 开源,因此下载了最新的源代码(撰写本文时为 2.00 RC3)并在文件中 \pdfbox-2.0.0-RC3\pdfbox\src\main\java\org\apache\pdfbox\multipdf\PDFMergerUtility.java(第 188 行附近)

我们可以看到它从较低的级别向上抛出这个异常,并没有捕获它并添加导致错误的文件的详细信息。

在解决此问题之前,您必须在代码中捕获此错误并迭代加载和关闭它们的每个源文件,直到找到不会修复的源文件能够自行处理和报告。

如果您有兴趣从源头(PDFBox 内)解决问题,那么这是要进行的编辑并提交给 PDFBox 项目团队。当该修复被合并到构建中并且您升级到该版本时,您可以安全地删除您的迭代代码:

        try
        {
            MemoryUsageSetting partitionedMemSetting = memUsageSetting != null ? 
                    memUsageSetting.getPartitionedCopy(sources.size()+1) :
                    MemoryUsageSetting.setupMainMemoryOnly();
            Iterator<InputStream> sit = sources.iterator();
            destination = new PDDocument(partitionedMemSetting);

            while (sit.hasNext())
            {
                sourceFile = sit.next();
                source = PDDocument.load(sourceFile, partitionedMemSetting);
                tobeclosed.add(source);
                appendDocument(destination, source);
            }
            if (destinationStream == null)
            {
                destination.save(destinationFileName);
            }
            else
            {
                destination.save(destinationStream);
            }
        }

catch (IOException e) { /* 插入代码以将其置于内部异常中并抛出一个包括命名的 'sourceFile' */ }


        finally
        {
            ....}

【讨论】:

  • addSource 方法不会抛出异常(您只是在构建要合并的 PDF 列表)。它是引发异常的 mergeDocuments 方法。
  • 对不起 - 意味着合并操作。如果合并操作在其中一个源不是 PDF 的情况下发生故障,并且它给您的异常没有指定失败的源文件的详细信息或内部信息,那么您必须自己解决问题。跨度>
  • 所有来源均为 PDF。他们在 Adob​​e 或 Evince(Linux,文档查看器)中查看良好。我已将堆栈跟踪添加到上面的问题中。您如何确定哪些来源失败了?
  • 好的,我现在看到你的编辑了。这在技术上是可行的,但如果有更有效的方法就更好了。
  • 你是对的。我已经开始更新我的代码以捕获异常,然后找出哪些源失败了。它远没有我所拥有的那么优雅。稍后,我会整理一个补丁提交给 Apache。
猜你喜欢
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
  • 2015-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多