我目前有一个项目,其中有许多表单被处理并存储在数据库中。成功完成后,将通过电子邮件通知管理员该表单提交的内容。
问题是这些表格之一我需要它看起来完全像我的 PDF 格式的邮购版本。
所以我有两个基本选择:
我知道选项 1 是可行的。我以前做过类似的事情。问题是表格非常复杂,有很多坐标需要计算...此外,这个过程有很多试验和错误。
选项 2 似乎会更容易,只要我可以通过迭代或名称/id 访问字段并设置值即可。
所以我的问题是,Zend_Pdf 是否支持对 PDF 表单域的操作?除了提交和重置表单操作外,我在 API 中看不到任何表示它支持此操作的内容。
此外,如果有其他支持选项 2 的 OO F/OSS PDF 库,我将有兴趣了解它们以及任何替代方法。
最佳答案
prodigitalson,我想为您发布这个解决方案,以防您仍然对寻找答案感到好奇。它只适用于为 1.5 版 (Acrobat 6.0) 优化的 PDF,但它确实工作得很好。它是 Zend Framework 1.12.3 的非官方补丁,用于填充 PDF 表单字段。 Site with the discussion and patch
没有安装,没有外部程序,没有坐标
首先使用如下内容更新您的 php.ini 文件(注意:当我上传这些更改时,我将不得不更改我实际网络服务器上的 .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 available here版权所有 (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 文件并替换下面的所有行'+' 在它们前面。您可以通过位置标记 '@@ -202,6 +202,13 @@' 找到它们的位置,它就在第 200 行附近,然后只需复制并粘贴以替换旧代码新的):
--- 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.
关于php - Zend_Pdf 操作 PDF 表单域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3814094/
我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我需要一个表,其中行实际上是2行表,一个嵌套表是..我怎样才能在Prawn中做到这一点?也许我需要延期..但哪一个? 最佳答案 现在支持子表:Prawn::Document.generate("subtable.pdf")do|pdf|subtable=pdf.make_table([["sub"],["table"]])pdf.table([[subtable,"original"]])end 关于ruby-on-rails-PrawnPDF:Ineedtogeneratenested
我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption
我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?
在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.
a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],
我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful
我有一个非常简单的Controller来管理我的Rails应用程序中的静态页面:classPagesController我怎样才能让View模板返回它自己的名字,这样我就可以做这样的事情:#pricing.html.erb#-->"Pricing"感谢您的帮助。 最佳答案 4.3RoutingParametersTheparamshashwillalwayscontainthe:controllerand:actionkeys,butyoushouldusethemethodscontroller_nameandaction_nam
我在事件管理员编辑页面中有嵌套资源,但我只想允许管理员编辑现有资源的内容,而不是添加新的嵌套资源。我的代码看起来像这样:formdo|f|f.inputsdof.input:authorf.input:contentf.has_many:commentsdo|comment_form|comment_form.input:contentcomment_form.input:_destroy,as::boolean,required:false,label:'Remove'endendf.actionsend但它在输入下添加了“添加新评论”按钮。我怎样才能禁用它,并只为主窗体保留f.ac