我目前有一个项目,有许多表格在DB中处理和存储。成功完成后,将通过电子邮件通知管理员该表单提交的内容。
问题在于其中一种形式,我需要它看起来与PDF格式的邮购版本完全相同。
所以我有两个基本选择:
选项1我知道是可行的。我之前做过类似的事情。问题是形式相当复杂,有很多坐标可以解决......而且,这个过程有很多反复试验。
选项2似乎更容易,只要我可以通过迭代或名称/ ID访问字段并只设置值。
所以我的问题是,Zend_Pdf是否支持PDF表单字段的操作?除了提交和重置表单操作之外,我在API中没有看到任何表示它支持此操作的内容。
此外,如果有其他支持选项2的OO F / OSS PDF库,我将有兴趣了解它们以及任何其他方法。
答案 0 :(得分:4)
prodigitalson,我想为你发布这个解决方案,以防万一你仍然想要找到答案。它仅适用于针对1.5版(Acrobat 6.0)优化的PDF,但它确实可以正常工作。这是Zend Framework 1.12.3填写PDF表单字段的非官方补丁。 Site with the discussion and patch
没有安装,没有外部程序,没有坐标
首先使用以下内容更新您的php.ini文件(注意:当我上传这些更改时,我将不得不在我的实际Web服务器上更改我的.ini文件):
include_path = ".;C:\wamp\www\includes"
请注意:我将所有库内容从'ZendFramework-1.12.3 \ library'文件夹移到一个名为Zend:C:\wamp\www\includes\Zend
的文件夹中,只是为了便于引用库(这就是你的全部内容)无论如何都需要。)
然后在你的php文件中(我使用'DIRECTORY_SEPARATOR',这样你就可以在Win或Unix服务器上使用它,我不需要根据我的.php文件的位置进行任何代码更改,我会只需要更改服务器配置):
require_once('Zend'.DIRECTORY_SEPARATOR.'Loader'.DIRECTORY_SEPARATOR.'Autoloader.php');
$loader = Zend_Loader_Autoloader::getInstance();
$loader->registerNamespace('Zend_');
然后为实际代码使用:
$pdf = Zend_Pdf::load('input-file-containing-form.pdf');
$pdf->setTextField('name', 'Someone');
$pdf->setTextField('address', '1 Main Street');
$pdf->setTextField('city', 'Cyberspace');
$pdf->save('outputfile.pdf');
或者我为了我的目的而这样做(我还包括我用来通过电子邮件发送完成的就业应用程序然后删除.pdf文件以便它不会阻塞我的服务器的代码:attach_mailer_class.php {{3版权所有(c)2006,Olaf Lederer):
// Write $_POST form data to associative array
foreach ($_POST as $key => $value) {
$NameArray[$key] = $value;
}
// Path to PDF application fillable file
$pdf_path = dirname(__FILE__) . "\\docs";
$pdf_filename = 'employment_applicationJBzend.pdf';
$pdf_file_path = $pdf_path . "\\" . $pdf_filename;
// Path to PDF application file save location
$result_path = dirname(__FILE__) . "\\results";
$result_filename = ucfirst($_POST['first_name']) . ucfirst($_POST['last_name']) . $filedatetime . '.pdf';
$result_file_path = $result_path . "\\" . $result_filename;
//Filling PDF fields | Example: $pdf->setTextField('position_applied_for', 'IT Manager');
$pdf = Zend_Pdf::load($pdf_file_path);
foreach ($NameArray as $key1 => $value) {
foreach($ExceptionArray as $key2 => $value)
{
if($key1 == $ExceptionArray[$key2]){
$boolSetText = false;
break;
}else{
$boolSetText = true;
}
}
if($boolSetText){
$pdf->setTextField($key1, $NameArray[$key1]);
}
}
$pdf->save($result_file_path);
//Create and send message using 'attach_mailer_class.php
$email = new attach_mailer($from_name, $from_mail, $mail_to, $cc = "", $bcc = "", $subject);
$email->text_body = $message;
$email->add_attach_file($result_file_path);
// $email->add_attach_file("ip2nation.zip");
$email->process_mail();
unlink($result_file_path);
如果页面不再存在,这里是PDF.php的补丁(如果您不知道如何运行实际的补丁,基本上您将浏览PDF.php文件并替换下面的所有行在他们面前的'+'。您可以通过位于第200行的位置标记'@@ -202,6 +202,13 @@'找到它们的位置,然后只需复制并粘贴以替换旧代码新的):
--- Pdf.php.orig 2009-11-15 17:52:57.000000000 +0100
+++ Pdf.php 2010-01-07 04:05:23.000000000 +0100
@@ -202,6 +202,13 @@
* @var array
*/
protected static $_inheritableAttributes = array('Resources', 'MediaBox', 'CropBox', 'Rotate');
+
+ /**
+ * List of form fields
+ *
+ * @var array - Associative array, key: name of form field, value: Zend_Pdf_Element
+ */
+ protected $_formFields = array();
/**
* Request used memory manager
@@ -315,6 +322,7 @@
$this->_loadNamedDestinations($this->_trailer->Root, $this->_parser->getPDFVersion());
$this->_loadOutlines($this->_trailer->Root);
+ $this->_loadFormfields($this->_trailer->Root);
if ($this->_trailer->Info !== null) {
$this->properties = $this->_trailer->Info->toPhp();
@@ -557,6 +565,61 @@
$this->_originalOpenOutlinesCount = $root->Outlines->Count->value;
}
}
+
+ /**
+ * Load form fields
+ * Populates the _formFields array, for later lookup of fields by name
+ *
+ * @param Zend_Pdf_Element_Reference $root Document catalog entry
+ */
+ protected function _loadFormFields(Zend_Pdf_Element_Reference $root)
+ {
+ if ($root->AcroForm === null || $root->AcroForm->Fields === null) {
+ return;
+ }
+
+ foreach ($root->AcroForm->Fields->items as $field)
+ {
+ if ( $field->FT->value == 'Tx' && $field->T !== null ) /* We only support fields that are textfields and have a name */
+ {
+ $this->_formFields[$field->T->value] = $field;
+ }
+ }
+
+ if ( !$root->AcroForm->NeedAppearances || !$root->AcroForm->NeedAppearances->value )
+ {
+ /* Ask the .pdf viewer to generate its own appearance data, so we do not have to */
+ $root->AcroForm->add(new Zend_Pdf_Element_Name('NeedAppearances'), new Zend_Pdf_Element_Boolean(true) );
+ $root->AcroForm->touch();
+ }
+ }
+
+ /**
+ * Retrieves a list with the names of the AcroForm textfields in the PDF
+ *
+ * @return array of strings
+ */
+ public function getTextFieldNames()
+ {
+ return array_keys($this->_formFields);
+ }
+
+ /**
+ * Sets the value of an AcroForm text field
+ *
+ * @param string $name Name of textfield
+ * @param string $value Value
+ * @throws Zend_Pdf_Exception if the textfield does not exist in the pdf
+ */
+ public function setTextField($name, $value)
+ {
+ if ( !isset($this->_formFields[$name]))
+ throw new Zend_Pdf_Exception("Field '$name' does not exist or is not a textfield");
+
+ $field = $this->_formFields[$name];
+ $field->add(new Zend_Pdf_Element_Name('V'), new Zend_Pdf_Element_String($value) );
+ $field->touch();
+ }
/**
* Orginize pages to tha pages tree structure.
答案 1 :(得分:2)
对不起,这有点晚了,但认为这可能有用......
如果您有权向服务器添加额外的组件,那么您可以使用PDF Labs PDF Tooklit(pdftk)库 - 它是一个命令行实用程序,但显然可以通过PHP中的system / exec / passthru命令访问。您可以在此处查看pdftk信息:http://www.pdflabs.com/docs/pdftk-man-page/ PDFTK将允许您合并PDF,添加背景PDF并填写PDF中的表单字段(加上更多内容) - 请参阅fill_form开关。
如果您可以将pdftk添加到您的服务器,那么您还可以使用Andrew Heiss的pdftk-php类,以便更轻松地从您的数据库中提取的信息更新pdf中的表单字段 - 您可以在以下位置查看更多信息:{ {3}}
最后一条评论 - 如果您想直接从HTML中动态创建PDF,那么到目前为止最好的解决方案是WKHTML2PDF - https://github.com/andrewheiss/pdftk-php/ - 它基本上就像任何HTML屏幕的PDF屏幕截图(一点点)比这更复杂,但你明白了。)
正如您可能已经知道我刚刚处理过一个非常类似的问题,并且经历了许多令人头疼的事情以获得有效的解决方案。