php - 使用 mikehaertl\php-pdftk 库来操作 PDF,首先调用 getDataFields 时链接命令失败
问题描述
我正在尝试围绕mikehaertl\php-pdftk\pdf对象创建一个包装类,以填充 PDF 表单字段。当尝试通过文档链接命令时,pdf 无法正确执行第二个命令(或第一个命令之后的任何命令)。看起来这是底层临时文件处理的问题,并且在我查看临时文件夹时没有写出 tmep 文件。当我调试时,临时文件在那里,但大小为 0。
演示问题的示例代码
use mikehaertl\pdftk\Pdf;
class PDFTKTest extends TestCase
{
public function testPdfTkOperations()
{
$cmdPath = 'D:\PDFtk\bin\pdftk.exe';
$formPath = 'D:\test\sample_files\test.pdf';
$options = ['command' => $cmdPath];
$pdf = new Pdf($formPath, $options);
$this->assertNotNull($pdf);
//Get fields from PDF
$fields = $pdf->getDataFields();
$this->assertNotNull($fields);
//Set some field Values
$values = ['full_name' => 'John Q. Programmer'];
$pdf2 = new Pdf($pdf, $options); //chaining broken
//$pdf2 = new Pdf($formPath, $options); //works fine creating a new Pdf object
$this->assertNotNull($pdf2);
$res = $pdf2->fillForm($values)->execute();
//Next assertion fails using chaining
$this->assertTrue($res, "Execute failed: \n". $pdf2->getError());
//Get fields with the updates
$fields = $pdf2->getDataFields();
$this->assertNotNull($fields);
//Next assertion fails, getDataFields fails on a chained command
$this->assertGreaterThan(0, count($fields));
}
}
我有一个解决方法,我为每个操作使用单独的 \Pdf 对象并管理我自己的临时文件,我只是希望能够更多地利用类功能,而不必做那么多平凡的事情。此功能是否损坏,还是我使用不正确?
解决方案
在深入研究了 mikehaertl\php-pdftk\pdf 包装的PDFTK 库并阅读了有关dump_data_fields选项的文档后,我得出了以下观察结果:
- PDFTK 不会为 dump_data_fields 命令生成输出文件
- php-pdftk 类在调用 getDataFields 时确实会创建底层临时文件,但它是空的并且保持不变。
- 链接另一个 Pdf 对象时,它会引用上一个命令中的空临时文件。问题就在这里。
解决方案
当我调用 getFieldData 时,我创建了一个新的 Pdf 对象并将其链接到前一个对象,但是我不保存对它的引用。如果它是创建实际输出的命令,我只会保存新链接的对象。
这是一个演示的例子:
<?php
use mikehaertl\pdftk\Pdf;
class PDFTKFormService
{
protected $pdf = null;
/**
* @return array|bool|\mikehaertl\pdftk\DataFields
*/
public function getDataFields()
{
//get data fields doesn't output a new file
//so we need to use the existing instance or create a new one and
$pdf = $this->getNextPdf();
$fields = $pdf->getDataFields();
if ($fields === false)
return [];
return $fields;
}
/**
* @param array $data
*
* @return resource The stream resource
*/
public function setDataFieldValues($data = [])
{
$this->pdf = $this->getNextPdf();
$this->pdf->fillForm($data)->execute();
}
protected function getNextPdf()
{
$options = ['command' => 'Path\To\PDFTK\binary'];
if ($this->pdf === null) {
return new Pdf($this->getTemplatePath(), $options);
} else {
return new Pdf($this->pdf, $options);
}
}
}
希望这可以帮助别人。
推荐阅读
- mysql - 在 SELECT ... INNER JOIN ... FOR UPDATE 的情况下,字符串的顺序是什么锁定以及如何避免死锁?
- mysql - SQL 查询顺序
- css - nodejs,背景图像css不起作用
- c++ - c++ std::regex 中前瞻中的无效反向引用
- c# - 如何在 Xamarin 的 api 控制器中使用异步方法
- selenium-webdriver - 在 selenium 中实现页面工厂模型时,我遇到类未找到异常
- python-3.x - 如何在 Python 中生成随机字符串字符的随机序列
- java - 获取资源包中的所有文件名并为 nonjar 和 jar 运行工作
- java - 在文件输入输出java中使用arraylist
- r - 用 arctan 逼近曲线