How to fill PDF form in php

2019-01-30 00:30发布

问题:

I have many PDF forms, I would need to fill them each in php with the data I already have.

Here is just a sample PDF form , I want to fill this form using php. The data I already have in DB. I just want to fill this form and save it.

I am working in PHP Zend Framework.

All I want is when I would download those forms from my site, it would pre-fill all the fields in the pdf form with the information I already have.

Please help me.

回答1:

Calling pdftk is a nice way to accomplish this. I'll assume that you know how to execute an external program and leave that out.

First, create an FDF file from your PDF.

pdftk form.pdf generate_fdf output data.fdf

You can now use that as template. The sample that you provided looks like this:

%FDF-1.2
%<E2><E3><CF><D3>
1 0 obj 
<<
/FDF 
<<
/Fields [
<<
/V ()
/T (Date)
>> 
<<
/V /
/T (CheckBox2)
>> 
<<
/V /
/T (CheckBox3)
>> 
<<
/V /
/T (CheckBox4)
>> 
<<
/V /
/T (CheckBox5)
>> 
<<
/V ()
/T (Your_Last_Name)
>> 
<<
/V ()
/T (Your_First_Name)
>> 
<<
/V /
/T (CheckBox1)
>>]
>>
>>
endobj 
trailer

<<
/Root 1 0 R
>>
%%EOF

The fields are lines that start with /V (). Enter your desired values into those fields. For example:

%FDF-1.2
%<E2><E3><CF><D3>
1 0 obj 
<<
/FDF 
<<
/Fields [
<<
/V (February 4, 2012)
/T (Date)
...

Finally, merge the FDF with the PDF. Execute the command:

pdftk form.pdf fill_form data.fdf output form_with_data.pdf

If you don't need to keep the FDF and generated PDF files, you can simply pipe the data via stdin and stdout instead of using temp files.



回答2:

I found this and it works for me. It is an unofficial patch for Zend to fill FDF Form Fields.Site with the discussion and patch

NO INSTALLATION, NO OUTSIDE PROGRAMS, NO COORDINATES

Use:

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

If page no longer exists here is the patch for PDF.php (if someone have problems - write me privete message):

--- 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.


回答3:

The Zend_Pdf-component can draw text in your pdf, but it is a bit clumsy as you have to specify the x- and y-coordinates on your pdf-page. Something like that:

// This is the pdf-file you want to fill out...
$pdf = Zend_Pdf::load('/path/to/pdf-template.pdf')
$page = $pdf->pages[0]; // Use first page
$page->drawText("firstname lastname", 200, 600);
...
$pdf->pages[0] = $page;
// be sure to write to a new file, not the original empty  form.
$pdf->save('/path/to/pdf-output.pdf');

I don't know if there are easy ways to find the exact coords, I usually play around until it fits.



回答4:

I found fpdf library looking for the same on internet.

http://www.fpdf.org/en/script/script93.php

Code looks clean, easy to use and remember it, and works for pdf with forms (fillable).

<?php

/***************************
  Sample using a PHP array
****************************/

require('fpdm.php');

$fields = array(
    'name'    => 'My name',
    'address' => 'My address',
    'city'    => 'My city',
    'phone'   => 'My phone number'
);

$pdf = new FPDM('template.pdf');
$pdf->Load($fields, false); // second parameter: false if field values are in ISO-8859-1, true if UTF-8
$pdf->Merge();
$pdf->Output();
?>

It comes with example that worked out of the box. Hope it helps.



回答5:

If you don't mind installing Drupal and setting up a simple site, you can install the Fill PDF module and configure it. If you already have the data, then this might be overkill, but if you can import that data into Drupal somehow (like with the Feeds module, for example), then you would save time on writing PDF-filling code. You can use a hosted service with that module or install stuff on your server.

Disclaimer: I maintain that module and run the hosted service.