pdftk错误:无法打开PDF文件:

10

我正在使用 pdftk 库从 pdf 文件中提取表单字段。除了一个问题,一切都运行良好,即我遇到了一个 pdf 文件pdf 文件链接,导致下面给出的错误。

Error: Failed to open PDF file: 
   http://www.uscis.gov/sites/default/files/files/form/i-9.pdf
Done.  Input errors, so no output created.

这个命令是

root@ri8-MS-7788:/home/ri-8# pdftk http://192.168.1.43/form/i-9.pdf dump_data_fields

相同的命令适用于所有其他表格。

尝试1

我尝试将pdf加密为不安全版本,但它产生了相同的错误。这是命令:

pdftk http://192.168.1.43/forms/i-9.pdf input_pw foopass output /var/www/forms/un-i-9.pdf

更新

这是我处理此事的完整功能。

public function Formanalysis($pdfname) 
    {
         $pdffile=Yii::app()->getBaseUrl(true).'/uploads/forms/'.$pdfname;
        exec("pdftk ".$pdffile." dump_data_fields 2>&1", $output,$retval);
        //got an error for some pdf if these are secure 
        if(strpos($output[0],'Error') !== false)
        {
            $unsafepdf=Yii::getPathOfAlias('webroot').'/uploads/forms/un-'.$pdfname;
            //echo "pdftk ".$pdffile." input_pw foopass output ".$unsafepdf;
            exec("pdftk ".$pdffile." input_pw foopass output ".$unsafepdf);
            exec("pdftk ".$unsafepdf." dump_data_fields 2>&1", $outputunsafe,$retval);
            return $outputunsafe ;
            //$response=array('0'=>'error','error'=>$output[0]);
            //return $response;

        }

        //if (strpos($output[0],'Error') !== false){ echo  "error to run" ; }   // this is the option to handle error 
        return $output;

    }

你可以使用pdftk,但需要注意以下细节:1 = 下载并使用最新版本或从pdflabs.com/docs/pdftk-version-history编译; 2 = 此PDF已应用限制(所有者密码);在使用pdftk之前,您需要去除这些限制。您可以使用qpdf qpdf.sourceforge.net qpdf --decrypt *.pdf output.pdf 来做到这一点,然后就可以轻松使用pdftk了。 - Dingo
实际上,只有非常旧的版本(pdftk 1.41)不支持PDF版本> 1.4 / 1.5,更新的版本完全支持这些版本及以上。 - Dingo
2个回答

14
PdfTk是一个工具,它通过使用GNU Java编译器(GCJ)将 iText的过时版本编译成可执行文件而创建(PdfTk不受iText Group NV的认可)。
我已经检查了您的PDF文件,它使用了两种当时iText不支持的技术:XFA和压缩交叉引用表。
后者是导致问题的原因。PdfTk期望您的文件以这种方式结束:
xref
0 7
0000000000 65535 f 
0000000258 00000 n 
0000000015 00000 n 
0000000346 00000 n 
0000000146 00000 n 
0000000397 00000 n 
0000000442 00000 n 
trailer
<</ID [<c8bf0ac531b0fc7b5b9ec5daf0296834><ec4dde54d00305ebbec62f3f6bbca974>]/Root 5 0 R/Size 7/Info 6 0 R>>
%iText-5.4.3
startxref
595
%%EOF

在这个片段中,startxref 标记了 xref 的字节偏移量,这是交叉引用表开始的地方。该表包含 PDF 中所有对象的字节偏移量。
当您查看所引用的 PDF 时,您会发现它以这样结束:
64 0 obj
<</DecodeParms<</Columns 5/Predictor 12>>/Encrypt 972 0 R/Filter/FlateDecode/ID[<85C47EA3EFE49E4CB0F087350055FDDC><C3F1748360D0464FBA02D711DE864630>]/Info 970 0 R/Length 283/Root 973 0 R/Size 971/Type/XRef/W[1 3 1]>>stream
hÞìÒ±JQЙ·»7J¢©ÕØ(Xþ„ù »h%¤É¤¶”€mZ+;ÁN,,ÁÆ6 XÁ&‚("î½YŒI‘Bî‡áμ]ö1Áð÷³cfþ‹ûÐÚLî`z„Ýôœùw÷N×X?ÙkNv`hÁÒj¦G[œiÀå»›œ?b½Än…ÉëàÍþ gY—i7WW‡òj®îÍ°u¸Ò‡Ñ:óÆÛ™ñÎë&'×݈§ü†ù!ÿñ€ù%,\ácçÙ9˜ì±Þ€S¼Ãd—‰Áy~×.ø¶Åìþßn_˜$9Ôüw£X9#åxzçgRüüóÙwÝ¡œÄNJ©½’Ú+©½’R{%µWR{%ÿ·á”;`_ z6Ø
endstream
endobj
startxref
116
%%EOF

在这种情况下,startxref 仍然指的是第一个交叉引用表开始的位置(它是一个线性化的PDF),但是交叉引用表存储在一个对象内,并且该对象被压缩(请参见 streamendstream 关键字之间的无意义字符)。
压缩的交叉引用表和压缩的对象是在PDF 1.5(2003年)中引入的,但是它们不受PdfTk支持。您需要找到一个能够处理此类流的工具(例如iText的最新版本,与PdfTk相比是真正的东西),或者在使用PdfTk处理之前将您的PDF保存为PDF 1.4(但您将失去XFA,因为XFA也是在PDF 1.5中引入的)。
更新:
由于您询问表单字段,我添加了以下附件:

enter image description here

这个屏幕截图是使用iText RUPS拍摄的(证明iText可以打开该文档)。在右侧,您可以看到同一个表单被定义了两次:

enter image description here

如果您在“字段”下面向下滚动,您会发现使用AcroForm技术存储在PDF中的所有字段。在左侧,您可以看到这样一个字段的描述:

enter image description here

如果您查看XFA,您会注意到同一表单也使用XML Forms Architecture进行了定义。如果您点击 数据集,您将在下面的面板中看到数据集的XML描述:

enter image description here

所有这些信息都可以通过使用iText(Java)或iTextSharp(C#)进行编程访问。 PdfTk仅是基于此技术非常旧版本的工具。

你能否推荐一个相关的库? - Manoj Dhiman
我提到了iText,它可用于Java和C#。正如我所解释的那样:当您使用PdfTk时,您已经在使用过时的iText版本。最近的iText版本支持具有压缩交叉引用表的文件。我将在我的答案中添加一个iText RUPS屏幕截图。 - Bruno Lowagie
我能在PHP中使用iText吗? - Manoj Dhiman

11

这可能是一个有点巧妙的解决方案,但应该能适用于你。就像@bruno说的那样,这是一个加密文件。在使用pdftk之前,您应该对其进行解密。为此,我找到了一种解密方法,即qpdf,它是一个免费的开源库,可以解密pdf文件、删除所有者和用户密码等等。您可以在这里找到它:Qpdf。在系统上安装它,并运行此命令。

qpdf --decrypt input.pdf output.pdf

然后在 pdftk 命令中使用输出文件。它应该可以工作。


布鲁诺在哪里说这个文档被加密了? - David van Driessche
这个解密似乎很有用,当我试图将一个问题儿童的Word pdf与其他一些pdf合并时。 - ryanjdillon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接