代码之家  ›  专栏  ›  技术社区  ›  prodigitalson

Zend_PDF操作PDF表单字段

  •  4
  • prodigitalson  · 技术社区  · 14 年前

    我目前有一个项目,在数据库中处理和存储了许多表单。成功完成后,将通过电子邮件通知管理员该表单提交的内容。

    问题是,对于其中一个表单,我需要它看起来与我的PDF格式的邮购版本完全相同。

    所以我有两个基本选择:

    1. 计算出我需要写入的“字段”的所有坐标,然后在这些坐标处覆盖我绘制的文本。
    2. 使用Acrobat Pro的表单向导将PDF转换为PDF表单,然后以编程方式设置字段值

    我知道选择1可行。我以前也做过类似的事情。问题是形式很复杂,有很多坐标要计算…此外,这一过程还存在许多尝试和错误。

    选项2似乎更简单,只要我可以通过迭代或名称/id访问字段并设置值。

    所以我的问题是,Zend_PDF是否支持对PDF表单字段的操作?除了提交和重置表单操作之外,我在API中没有看到其他表示它支持这一点的内容。

    另外,如果有其他的OOF/OSS PDF库支持选项2,我将有兴趣了解它们以及其他任何方法。

    2 回复  |  直到 9 年前
        2
  •  4
  •   Radish    11 年前

    Site with the discussion and patch

    include_path = ".;C:\wamp\www\includes"
    

    C:\wamp\www\includes\Zend

    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');
    

    available here

    // 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.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.
    
    推荐文章