4

私は現在プロジェクトを持っており、処理されてDBに保存されるフォームがいくつかあります。正常に完了すると、管理者はそのフォーム送信の内容を電子メールで通知されます。

問題は、これらのフォームの1つで、PDF形式の通信販売バージョンとまったく同じように表示する必要があることです。

したがって、2つの基本的なオプションがあります。

  1. 書き込む必要のある「フィールド」のすべての座標を把握し、それらの座標に描画したテキストをオーバーレイします
  2. Acrobat Proのフォームウィザードを使用してPDFをPDFフォームに変換し、プログラムでフィールド値を設定します

オプション1私が知っていることは実行可能です。私は以前に同様のことをしました。問題は、フォームがかなり複雑で、理解するための座標がたくさんあることです...さらに、このプロセスには多くの試行錯誤があります。

オプション2は、反復または名前/ IDを介してフィールドにアクセスし、値を設定するだけでよい限り、より簡単なようです。

だから私の質問は、Zend_PdfはPDFフォームフィールドの操作をサポートしていますか?これをサポートしていることを示す、フォームの送信アクションとリセットアクション以外のAPIには何も表示されません。

さらに、オプション2をサポートする他のOO F / OSS PDFライブラリがある場合は、それらについて、および代替アプローチについて聞くことに興味があります。

4

2 に答える 2

4

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 ファイルを削除してサーバーが詰まらないようにするために使用したコードも含めました 2006年、オラフ・レデラー):

// 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.
于 2013-10-03T16:27:04.880 に答える
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クラスを使用して、DBから取得した情報からpdfのフォームフィールドを簡単に更新することもできます。詳細については、https://をご覧ください。 github.com/andrewheiss/pdftk-php/

最後のコメント-HTMLから直接PDFをオンザフライで作成したい場合は、WKHTML2PDFが最適なソリューションです-http : //code.google.com/p/wkhtmltopdf/-基本的にはPDFのスクリーンショットのように機能します任意のHTML画面(それより少し複雑ですが、あなたは考えを理解します)。

おそらくお分かりのように、私は非常によく似た問題に取り組んでおり、実用的な解決策を得るために非常に多くの頭痛の種を経験してきました。

于 2011-07-07T12:46:31.483 に答える