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

时间:2015-05-15 12:27:37

标签: php pdf pdftk

我正在使用pdftk库从pdf中提取表单字段。除了我得到pdf文件pdf file link的一个问题外,一切正常。导致错误的原因如下:

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

同一命令适用于所有其他表单。

Attempt1

我曾尝试将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;

    }

2 个答案:

答案 0 :(得分:10)

PdfTk是通过使用GNU Compiler for Java(GCJ)将an obsolete version of iText编译为可执行文件而创建的工具(PdfTk未经iText Group NV认可)。

我检查了你的PDF,它使用了创建PdfTk时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相比,它是真正的东西),或者您需要在处理之前将PDF保存为PDF 1.4使用PdfTk(但您将失去XFA,因为XFA也在PDF 1.5中引入)。

<强>更新

由于您询问表单字段,我添加了以下附件:

enter image description here

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

enter image description here

如果您沿着Fields下的树走下去,您将使用AcroForm技术找到存储在PDF中的所有字段。在左侧,您可以看到这样一个字段的描述:

enter image description here

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

enter image description here

所有这些信息都可以使用iText(Java)或iTextSharp(C#)以编程方式访问。 PdfTk仅仅是基于该技术的旧版本的工具。

答案 1 :(得分:8)

这可能是一个小技巧解决方案,但应该适合你。正如@bruno所说,这是加密文件。在使用pdftk之前,您应该解密它。为此我找到了解密的方法qpdf一个免费的opem源库来解密pdf,删除所有者和用户密码等等。你可以在Qpdf找到这个。将其安装在您的系统上。并运行此命令

qpdf --decrypt input.pdf output.pdf

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