簡體   English   中英

Zend_Pdf操縱PDF表單字段

[英]Zend_Pdf manipulating PDF Form Fields

我目前有一個項目,有許多表格在DB中處理和存儲。 成功完成后,將通過電子郵件通知管理員該表單提交的內容。

問題是這些形式之一,我需要它看起來像我的PDF格式的郵購版本。

所以我有兩個基本選擇:

  1. 找出我需要寫入的“字段”的所有坐標,然后在這些坐標處覆蓋​​我繪制的文本
  2. 使用Acrobat Pro的表單向導將pdf轉換為pdf格式,然后以編程方式設置字段值

選項1我知道是可行的。 我之前做過類似的事情。 問題是形式相當復雜,並且有很多坐標可以解決......而且,這個過程有很多反復試驗。

選項2似乎更容易,只要我可以通過迭代或名稱/ ID訪問字段並只設置值。

所以我的問題是,Zend_Pdf是否支持PDF表單字段的操作? 我沒有在API中看到除提交和重置表單操作之外的任何內容,表示它支持此操作。

此外,如果有其他OO F / OSS PDF庫支持選項2,我將有興趣了解它們以及任何替代方法。

prodigitalson,我想為你發布這個解決方案,以防萬一你仍然想要找到答案。 它僅適用於針對1.5版(Acrobat 6.0)優化的PDF,但它確實可以正常工作。 這是Zend Framework 1.12.3填寫PDF表單字段的非官方補丁。 網站與討論和補丁

沒有安裝,沒有外部程序,沒有坐標

首先使用以下內容更新您的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 此處可用版權所有(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.

對不起,這有點晚了,但認為這可能有用......

如果您有權向服務器添加額外的組件,那么您可以使用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中的表單字段 - 您可以在以下網址查看更多信息: https:// github.com/andrewheiss/pdftk-php/

最后一條評論 - 如果您想直接從HTML創建PDF,那么到目前為止最好的解決方案是WKHTML2PDF - http://code.google.com/p/wkhtmltopdf/ - 它基本上就像PDF截圖任何HTML屏幕(比這更復雜,但你明白了)。

你可以告訴我,我剛剛解決了一個非常類似的問題,並且經歷了許多令人頭疼的事情以獲得一個有效的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM