关于php:pdftk错误:无法打开PDF文件:

pdftk Error: Failed to open PDF file:

我正在使用pdftk库从pdf中提取表单字段。除了我得到pdf文件pdf文件链接的一个问题之外,其他一切都运行良好。 导致错误的原因如下

1
2
3
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.

命令是

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

相同的命令适用于所有其他形式。

尝试1

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

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

更新资料

这是我的全部职责

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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是通过使用Java GNU编译器(GCJ)将过时版本的iText编译为可执行文件而创建的工具(iText Group NV不认可PdfTk)。

我已经检查了您的PDF,它使用了创建PdfTk时iText不支持的两种技术:XFA和压缩的交叉引用表。

后者是导致您的问题的原因。 PdfTk希望您的文件像这样结束:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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时,您会看到它像这样结束:

1
2
3
4
5
6
7
8
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
hTìò±JQD?·?7J¢???(Xt?ù ?h%¤é¤?"€mZ+;áN,,á?6 Xá&?("??Y?I‘B??á??]?1áe÷3cft??DúL?`z??Y??ùw÷N×X???kNv`háòj|G[?ià?????b??n…é?àít gY—i7WW?òj??í°u?ò??:ó??????&'×Y?§ü?ù!??€ù%,\\ác?ù9?ì±T€S??d—‰áy~×.???ìt?n_?$9?üw£X9#?xz?gRüüóùwY???NJ??’ú+??’R{%μWR{%?·á";`_ z6?
endstream
endobj
startxref
116
%%EOF

在这种情况下,startxref仍然指的是第一个交叉引用表的起始位置(它是线性化的PDF),但是交叉引用表存储在一个对象内部,并且该对象被压缩了(请参见stream之间的乱码和endstream关键字)。

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只是基于该技术的非常旧版本的工具。


这可能是一个小技巧,但是应该为您工作。如@bruno所说,这是加密文件。在用于pdftk之前,应先对此进行解密。为此,我找到了一种解密方法,即qpdf一个免费的opem源库,用于解密pdf,删除所有者和用户密码等,还有更多。您可以在这里找到Qpdf。在您的系统上安装它。并运行此命令

1
qpdf --decrypt input.pdf output.pdf

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