Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PDF form population with FPDM

what I'm trying to accomplish is population of PDF form with PHP.
I tried many ways, I found that FPDM (FPDF) is working well when I create a new form, or use the form from source file they provided.
My problem is when I'm using already created PDF form, the form has restrictions such as Owner password, document is signed and certified. I used the app to remove those restrictions, some of them are left. In picture below you can see how my current PDF looks like.

enter image description here

That PDF also was compressed, and because FPDM was throwing the error that 'Object Stream' is not supported I decompressed it through PDFTK, so file went from 1.48 Mb to 6.78 Mb.

To get all form field names I used also PDFTK, so I have them in txt file.

There are two ways I can do by the instructions of FPDM:

First way is only to send an array field_name => value along with PDF I want to change and that's it. So when I use PDF described above I get error:

'FPDF-Merge Error: field form1[0].#subform[0].Line1_GivenName[0] not found'

Just to remind that I have all names and this name exists.

<?php
require('fpdm.php');

$fields = array(
        'form1[0].#subform[0].Line1_GivenName[0]' => 'my name'
    );
$pdf = new FPDM('test.pdf');
$pdf->Load($fields, false); // second parameter: false if field values are in ISO-8859-     1, true if UTF-8
$pdf->Merge();
$pdf->Output('new_pdf.pdf', 'F');
?>

The other way is that I create FDF file with createXFDF function and then use FPDM to merge FDF to PDF. This solution creates 'new_file.pdf' like I want but empty :)

function createXFDF($file, $info, $enc = 'UTF-8') {
$data = '<?xml version="1.0" encoding="'.$enc.'"?>' . "\n" .
    '<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">' . "\n" .
    '<fields>' . "\n";
foreach($info as $field => $val) {
    $data .= '<field name="' . $field . '">' . "\n";
    if(is_array($val)) {
        foreach( $val as $opt )
            $data .= '<value>' .
                htmlentities( $opt, ENT_COMPAT, $enc ) .
                '</value>' . "\n";
    } else {
        $data .= '<value>' .
            htmlentities( $val, ENT_COMPAT, $enc ) .
            '</value>' . "\n";
    }
    $data .= '</field>' . "\n";
}
$data .= '</fields>' . "\n" .
    '<ids original="' . md5( $file ) . '" modified="' .
        time() . '" />' . "\n" .
    '<f href="' . $file . '" />' . "\n" .
    '</xfdf>' . "\n";

return $data;
}


require('fpdm.php');

$pdf = new FPDM('test.pdf', 'posted-0.fdf');
$pdf->Merge();
$pdf->Output('new_file.pdf', 'F');

One more thing, if I try to open FDF file in Acrobat I get a message

'The file you are attempting to open contains comments or form data that are supposed to be placed on test.pdf. This document cannot be found. It may have been moved, or deleted. Would you like to browse to attempt to locate this document?'

but the file is there, not moved or deleted. When I find it manually the form populates.

If anyone has experience with this, any help or advice would help a lot.

Thank you in advance, Vukasin

EDIT: More info about the PDF file enter image description here

like image 811
Wolf87 Avatar asked Nov 29 '22 14:11

Wolf87


2 Answers

Thanks to Kyle's answer, I resolved a similar issue.

I have a pdf created in Adobe Acrobat Pro DC and need to populate its form fields from web input.

On my development machine, I created an fdf file from my web form data, and merged it into the pdf using pdftk (called from php with exec() ).

But I couldn't put that on the cloud linux webserver where my site is hosted because it requires deprecated libraries.

So I switched to FPDM and had the following errors:

'Fast Web View mode is not supported'. I fixed that by setting preferences in 'save as' in Adobe Acrobat Pro (save as -> pdf optimized -> settings -> clean up -> uncheck Fast Web View).

'Object streams are not supported' - again, fixed in the 'save as' preferences (clean up -> object compression options -> remove compression).

'Incremental updates are not supported' - again, fixed using 'save as' in Acrobat.

Then FPDM ran, but couldn't read any field names.

The One-Step Solution:

Take the original file pdf - with incremental updates, object compression and fast web view - and pass it through pdftk on Windows, exactly as Kyle describes.

> pdftk broken.pdf output fixed.pdf

Now FPDM populates the fields correctly from the fdf file.

like image 31
HalfInHalf Avatar answered Dec 26 '22 11:12

HalfInHalf


I have spent more than a complete day working through issues with FPDM, and was hard pressed to find someone who had similar issues.

The following format worked for me: PDF 1.4 (Acrobat 5). I had to actually go to Save As -> choose Adobe PDF Optimized, then click the Settings button. From there I had to choose the version from the drop-down/fly-out menu.

I received the error: 'not compatible with fast web view' or similar. If in the PDF Optimized settings option you click 'clean up' on the left side you can untoggle fast web view.

Now I am receiving the error, PDF-Merge Error: field 'fieldname' not found. When I run it through pdftk hoping to resolve this, I receive the error: FPDF-Merge Error: Number of objects (35) differs with number of xrefs (36), something , pdf xref table is corrupted :(

To fix this issue, I had to download and install pdftk server utility on ubuntu

sudo apt-get install pdftk

After install, I ran this command to repair a PDF’s corrupted XREF table and stream lengths, if possible:

pdftk broken.pdf output fixed.pdf

When I open fixed.pdf it has no issues whatsoever and populates the fields correctly. Hallelujah this was the most annoying issue in the world. To summarize, I had to take the pdf and put it through the following steps:

  • Edit PDF to preference
  • Save As > .pdf optimized > Settings > Acrobat 5 > uncheck fast web under cleanup
  • Open file in pdftk and resave
  • Install command line pdftk via ubuntu
  • run command: pdftk broken.pdf output fixed.pdf

done.

like image 53
Kyle Burkett Avatar answered Dec 26 '22 11:12

Kyle Burkett