mikehaertl / php-pdftk
基于pdftk的PDF转换和表单工具。
Requires
- php: >=5.3.0
- mikehaertl/php-shellcommand: ^1.6.3
- mikehaertl/php-tmpfile: ^1.1.0
Requires (Dev)
- phpunit/phpunit: >4.0 <9.4
This package is auto-updated.
Last update: 2024-09-03 17:54:14 UTC
README
基于pdftk的PDF转换和表单工具。
功能
php-pdftk 将pdftk的全部功能引入PHP - 以及更多。
- 填写表单,可以从XFDF/FDF文件或数据数组中填写(适用于未压平表单的UTF-8安全,需要pdftk 2.x!)
- 从PHP数组创建XFDF或FDF文件(UTF-8安全!)
- 从填写好的PDF表单创建FDF文件
- 将多个PDF文件中的页面组合成一个新的PDF文件
- 将PDF拆分为每个页面一个文件
- 添加背景或覆盖PDF
- 读取PDF和表单字段的元数据
- 设置密码和权限
- 移除密码
需求
- pdftk命令必须在您的系统上安装并正常工作
- 此库是为pdftk 2.x版本编写的。您应该能够使用它与pdftk 1.x一起使用,但并非所有方法都适用。有关详细信息,请查阅系统上的pdftk man页面。
- 如果您从snap安装了pdftk包,Ubuntu上存在一个已知问题。此版本没有权限写入
/tmp
目录。您可以选择设置另一个临时目录,如下所述,或者使用另一个包。对于Ubuntu 18.10,apt还提供了通过apt安装的pdftk-java
包,应该可以正常工作。您也可以手动下载并安装此包。还可以查看askubuntu上的此答案。
注意:来自替代PPA
ppa:malteworld/ppa
的pdftk版本现在不再可用。作者现在指向上面链接的askubuntu上的答案。
安装
您应使用composer 安装此库。
composer require mikehaertl/php-pdftk
示例
为PDF文件创建实例
有多种方法可以告诉Pdf
实例它应该使用哪些文件。一些文件可能还需要密码或需要使用别名作为某些操作(例如cat或shuffle)中的处理程序。
注意:在pdftk的2.x版本中,处理程序可以是一个或多个大写字母。
// Create an instance for a single file $pdf = new Pdf('/path/to/form.pdf'); // Alternatively add files later. Handles are autogenerated in this case. $pdf = new Pdf(); $pdf->addFile('/path/to/file1.pdf'); $pdf->addFile('/path/to/file2.pdf'); // Add files with own handle $pdf = new Pdf(); $pdf->addFile('/path/to/file1.pdf', 'A'); $pdf->addFile('/path/to/file2.pdf', 'B'); // Add file with handle and password $pdf->addFile('/path/to/file3.pdf', 'C', 'secret*password'); // Shortcut to pass all files to the constructor $pdf = new Pdf([ 'A' => ['/path/to/file1.pdf', 'secret*password1'], 'B' => ['/path/to/file2.pdf', 'secret*password2'], ]);
操作
请参阅每个操作的pdftk man页面,以详细了解每个操作的工作方式以及可用的选项。
对于所有操作,您可以通过saveAs($name)
将PDF本地保存,或通过send()
将其发送到浏览器。如果您将文件名传递给send($name)
,则客户端浏览器将打开下载对话框,而不传递文件名则通常会在内联显示PDF。
重要:您始终只能对单个PDF实例执行以下操作之一。以下提供了一种解决方案,如果需要执行多个操作。
填写表单
使用来自PHP数组或XFDF/FDF文件的数据填写PDF表单。
use mikehaertl\pdftk\Pdf; // Fill form with data array $pdf = new Pdf('/full/path/to/form.pdf'); $result = $pdf->fillForm([ 'name'=>'ÄÜÖ äüö мирано čárka', 'nested.name' => 'valX', ]) ->needAppearances() ->saveAs('filled.pdf'); // Always check for errors if ($result === false) { $error = $pdf->getError(); } // Fill form from FDF $pdf = new Pdf('form.pdf'); $result = $pdf->fillForm('data.xfdf') ->saveAs('filled.pdf'); if ($result === false) { $error = $pdf->getError(); }
注意:当填写UTF-8数据时,您应始终添加needAppearances()
选项。这将确保PDF阅读器负责使用正确的字体进行渲染,这是pdftk无法为您做的。另外请注意,如果您的数据中有特殊字符,则flatten()
可能无法很好地工作。
如果您使用pdftk-java
>= 3.3.0且嵌入的字体不支持UTF-8字符,您还可以用本地字体替换它
use mikehaertl\pdftk\Pdf; // Fill form with data array $pdf = new Pdf('/full/path/to/form.pdf'); $result = $pdf->fillForm($data) ->replacementFont('/usr/share/fonts/dejavu/DejaVuSans.ttf') ->saveAs('filled.pdf');
从PHP数组创建XFDF/FDF文件
这是一个来自 pdftk
的不可用奖励功能。
use mikehaertl\pdftk\XfdfFile; use mikehaertl\pdftk\FdfFile; $xfdf = new XfdfFile(['name' => 'Jürgen мирано']); $xfdf->saveAs('/path/to/data.xfdf'); $fdf = new FdfFile(['name' => 'Jürgen мирано']); $fdf->saveAs('/path/to/data.fdf');
猫
从一个或多个 PDF 文件中的页面组装一个 PDF。
use mikehaertl\pdftk\Pdf; // Extract pages 1-5 and 7,4,9 into a new file $pdf = new Pdf('/path/to/my.pdf'); $result = $pdf->cat(1, 5) ->cat([7, 4, 9]) ->saveAs('/path/to/new.pdf'); if ($result === false) { $error = $pdf->getError(); } // Combine pages from several files $pdf = new Pdf([ 'A' => '/path/file1.pdf', // A is alias for file1.pdf 'B' => ['/path/file2.pdf','pass**word'], // B is alias for file2.pdf 'C' => ['/path/file3.pdf','secret**pw'], // C is alias for file3.pdf ]); $result = $pdf->cat(1, 5, 'A') // pages 1-5 from A ->cat(3, null, 'B') // page 3 from B ->cat(7, 'end', 'B', null, 'east') // pages 7-end from B, rotated East ->cat('end',3,'A','even') // even pages 3-end in reverse order from A ->cat([2,3,7], 'C') // pages 2,3 and 7 from C ->saveAs('/path/new.pdf'); if ($result === false) { $error = $pdf->getError(); }
洗牌
类似于 cat()
,但创建 "流",并一次填充新 PDF 中的一个页面。
use mikehaertl\pdftk\Pdf; $pdf = new Pdf([ 'A' => '/path/file1.pdf', // A is alias for file1.pdf 'B' => '/path/file2.pdf', // B is alias for file2.pdf ]); // new.pdf will have pages A1, B3, A2, B4, A3, B5, ... $result = $pdf->shuffle(1, 5, 'A') // pages 1-5 from A ->shuffle(3, 8, 'B') // pages 3-8 from B ->saveAs('/path/new.pdf'); if ($result === false) { $error = $pdf->getError(); }
爆炸
将 PDF 文件拆分为每页一个文件。
use mikehaertl\pdftk\Pdf; $pdf = new Pdf('/path/my.pdf'); $result = $pdf->burst('/path/page_%d.pdf'); // Supply a printf() pattern if ($result === false) { $error = $pdf->getError(); }
添加背景 PDF
将另一个 PDF 文件作为背景添加。
use mikehaertl\pdftk\Pdf; // Set background from another PDF (first page repeated) $pdf = new Pdf('/path/my.pdf'); $result = $pdf->background('/path/back.pdf') ->saveAs('/path/watermarked.pdf'); if ($result === false) { $error = $pdf->getError(); } // Set background from another PDF (one page each) $pdf = new Pdf('/path/my.pdf'); $result = $pdf->multiBackground('/path/back_pages.pdf') ->saveAs('/path/watermarked.pdf'); if ($result === false) { $error = $pdf->getError(); }
添加覆盖 PDF
将另一个 PDF 文件作为覆盖添加。
use mikehaertl\pdftk\Pdf; // Stamp with another PDF (first page repeated) $pdf = new Pdf('/path/my.pdf'); $result = $pdf->stamp('/path/overlay.pdf') ->saveAs('/path/stamped.pdf'); if ($result === false) { $error = $pdf->getError(); } // Stamp with another PDF (one page each) $pdf = new Pdf('/path/my.pdf'); $result = $pdf->multiStamp('/path/overlay_pages.pdf') ->saveAs('/path/stamped.pdf'); if ($result === false) { $error = $pdf->getError(); }
附件文件
将文件附件添加到文档或特定页面。
use mikehaertl\pdftk\Pdf; $files = [ '/path/to/file1', '/path/to/file2', ] // Add files at the document level $pdf = new Pdf('/path/my.pdf'); $result = $pdf->attachFiles($files) ->saveAs('/path/withfiles.pdf'); if ($result === false) { $error = $pdf->getError(); } // Add files to a specific page $pdf = new Pdf('/path/my.pdf'); $page = 7; $result = $pdf->attachFiles($files, $page) ->saveAs('/path/withfiles.pdf'); if ($result === false) { $error = $pdf->getError(); }
解包文件
将文件附件从 PDF 复制到指定目录。
use mikehaertl\pdftk\Pdf; $pdf = new Pdf('/path/my.pdf'); $result = $pdf->unpackFiles('/path/to/dir'); if ($result === false) { $error = $pdf->getError(); }
生成 FDF
从给定的填充 PDF 表单创建 FDF 文件。
use mikehaertl\pdftk\Pdf; // Create FDF from PDF $pdf = new Pdf('/path/form.pdf'); $result = $pdf->generateFdfFile('/path/data.fdf'); if ($result === false) { $error = $pdf->getError(); }
获取 PDF 数据
从 PDF 文件中读取元数据或表单字段信息。
use mikehaertl\pdftk\Pdf; // Get data $pdf = new Pdf('/path/my.pdf'); $data = $pdf->getData(); if ($data === false) { $error = $pdf->getError(); } // Get form data fields $pdf = new Pdf('/path/my.pdf'); $data = $pdf->getDataFields(); if ($data === false) { $error = $pdf->getError(); } // Get data as string echo $data; $txt = (string) $data; $txt = $data->__toString(); // Get data as array $arr = (array) $data; $arr = $data->__toArray(); $field1 = $data[0]['Field1'];
如何在 PDF 上执行多个操作
如上所述,您只能对单个 PDF 实例执行上述操作之一。如果您需要多个操作,可以将一个 Pdf
实例输入到另一个实例中
use mikehaertl\pdftk\Pdf; // Extract pages 1-5 and 7,4,9 into a new file $pdf = new Pdf('/path/my.pdf'); $pdf->cat(1, 5) ->cat([7, 4, 9]); // We now use the above PDF as source file for a new PDF $pdf2 = new Pdf($pdf); $result = $pdf2->fillForm(['name' => 'ÄÜÖ äüö мирано čárka']) ->needAppearances() ->saveAs('/path/filled.pdf'); if ($result === false) { $error = $pdf->getError(); }
选项
您可以将上述操作与以下一个或多个选项组合。
use mikehaertl\pdftk\Pdf; $pdf = new Pdf('/path/my.pdf'); $result = $pdf->allow('AllFeatures') // Change permissions ->flatten() // Merge form data into document (doesn't work well with UTF-8!) ->compress($value) // Compress/Uncompress ->keepId('first') // Keep first/last Id of combined files ->dropXfa() // Drop newer XFA form from PDF ->dropXmp() // Drop newer XMP data from PDF ->needAppearances() // Make clients create appearance for form fields ->setPassword($pw) // Set owner password ->setUserPassword($pw) // Set user password ->passwordEncryption(128) // Set password encryption strength ->saveAs('new.pdf'); if ($result === false) { $error = $pdf->getError(); } // Example: Fill PDF form and merge form data into PDF // Fill form with data array $result = $pdf = new Pdf('/path/form.pdf'); $pdf->fillForm(['name' => 'My Name']) ->flatten() ->saveAs('/path/filled.pdf'); if ($result === false) { $error = $pdf->getError(); } // Example: Remove password from a PDF $pdf = new Pdf; $result = $pdf->addFile('/path/my.pdf', null, 'some**password') ->saveAs('/path/new.pdf'); if ($result === false) { $error = $pdf->getError(); }
Shell 命令
该类使用 php-shellcommand 执行 pdftk
。您可以将 $options
作为其 Command
类的第二个参数传递给构造函数
use mikehaertl\pdftk\Pdf; $pdf = new Pdf('/path/my.pdf', [ 'command' => '/some/other/path/to/pdftk', // or on most Windows systems: // 'command' => 'C:\Program Files (x86)\PDFtk\bin\pdftk.exe', 'useExec' => true, // May help on Windows systems if execution fails ]);
解决文件名或 infofile 内容中的 UTF-8 字符问题
如果您有文件名中包含 UTF-8 编码字符的文件,或者您将包含此类字符的 infofile 传递给 updateInfo()
,则应在执行 pdftk
时提供正确的区域设置。因此,您可以添加以下选项
$pdf = new Pdf($file, [ 'locale' => 'en_US.utf8', 'procEnv' => [ 'LANG' => 'en_US.utf-8', ], ]);
注意:您需要确保您设置的区域设置在您的系统上可用。在 Linux 上,您可以使用
locale -a
检查已安装的区域设置。有关更详细的概念说明,请参阅这篇文章。
临时文件
内部通过 php-tmpfile 创建一个临时文件。您也可以直接访问该文件,例如,如果您既不希望发送也不希望保存文件,但只需要二进制 PDF 内容
use mikehaertl\pdftk\Pdf; $pdf = new Pdf('/path/my.pdf'); $result = $pdf->fillForm(['name' => 'My Name']) ->execute(); if ($result === false) { $error = $pdf->getError(); } $content = file_get_contents( (string) $pdf->getTmpFile() );
如果您有权限问题,可能需要设置一个目录,您的 pdftk
命令可以将其写入
use mikehaertl\pdftk\Pdf; $pdf = new Pdf('/path/my.pdf'); $pdf->tempDir = '/home/john/temp';
API
请参阅源文件以获取每个方法的完整文档。