kauffinger/php-pdftk-mcpdf

基于 mikehaertl/pdftk 和 vigicorp/php-mcpdf 的 PDF 转换和表单工具。可以与 mcpdf 动态使用。


README

GitHub Tests Packagist Version Packagist Downloads GitHub license Packagist PHP Version Support

基于 pdftk 和 mcpdf 的 PDF 转换和表单工具。

这是一个将 mcpdf 作为额外层粗略集成的例子 - 使用 php-pdftk 自定义命令使用 mcpdf。这专门用于填充包含 UTF-8 字符的表单。注意:此实现依赖于您已将“mcpdf”符号链接到执行 mcpdf。

功能

php-pdftk-mcpdpdftkmcpdf 的全部功能带入 PHP - 以及更多。

  • 从 XFDF/FDF 文件或数据数组(对未平整表单 UTF-8 安全,需要 pdftk 2.x!)中填充表单
  • 从 PHP 数组创建 XFDF 或 FDF 文件(UTF-8 安全!)
  • 从填充的 PDF 表单创建 FDF 文件
  • 将多个 PDF 文件的页面合并到新的 PDF 文件中
  • 将 PDF 分割成每个页面一个文件
  • 添加背景或叠加 PDF
  • 读取 PDF 和表单字段的元数据
  • 设置密码和权限
  • 删除密码

需求

  • pdftk 命令必须在您的系统上安装并正常工作
  • 如果想要写入 UTF-8 字符,mcpdf 命令必须在您的系统上安装并正常工作
  • 此库是为 pdftk 2.x 版本编写的。您应该能够使用它与 pdftk 1.x 一起使用,但并非所有方法都适用。有关详细信息,请咨询您系统上 pdftk 的手册页面。
  • 如果您从 snap 安装了 pdftk 软件包,Ubuntu 上存在一个已知问题。此版本没有权限写入 /tmp 目录。您可以设置另一个临时目录,如下所述,或者使用另一个软件包。对于 Ubuntu 18.10,还有通过 apt 可用的 pdftk-java 软件包,它应该可以正常工作。您也可以在 Ubuntu 18.04 上手动下载此软件包。还可以查看 askubuntu 上的此答案。

注意:来自替代 PPA ppa:malteworld/ppa 的 pdftk 版本不再可用。作者现在指向上面链接的 askubuntu 上的答案。

安装

这旨在作为您本地 php-pdftk 安装的直接替换。目前还没有 composer 软件包。

示例

为 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 手册页面,以了解每个操作如何详细工作以及哪些选项可用。

对于所有操作,您都可以通过 saveAs($name) 将 PDF 本地保存,或通过 send() 发送到浏览器。如果传递一个文件名到 send($name),则客户端浏览器将打开下载对话框;如果没有文件名,通常将显示 PDF 内联。

重要:您始终只能对单个 PDF 实例执行以下操作之一。以下您可以找到如果需要多个操作时的解决方案。

填充表单

使用 PHP 数组或 XFDF/FDF 文件中的数据填充 PDF 表单。注意如何使用选项数组创建 Pdf 实例。

use mikehaertl\pdftk\Pdf;

// Fill form with data array
$pdf = new Pdf('/full/path/to/form.pdf', [
            'command' => 'mcpdf'
        ]);
$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()可能不起作用。

从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
]);

临时文件

内部通过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

请参阅源文件以获取每个方法的完整文档。