I have an ebook in word that I convert to PDF before distributing to my clients. I'd like to dynamically insert their email address into all links in the ebook to allow them access to the members-only content on my site, and I'd like to do this on the fly, as part of the book download process.
I've briefly looked at http://us.php.net/pdf and FPDF, but I was wondering what specific technique I'd use to insert this data.
I was thinking I'd insert an email token string where I want the email address to go, and then use some function to update those tokens in the PDF document.
Can anyone point me in the right direction? I have php experience, but not with editing / generating pdf documents from php.
EDIT: Yes, this commercial script http://www.setasign.de/products/pdf-php-solutions/setapdf-linkreplacer/ does exactly what I needed.
So far it's looking like this is my best bet:
http://www.setasign.de/products/pdf-php-solutions/setapdf-linkreplacer/
Trying an eval copy of it, will update post with results.
you can do this with FPDI extension for FPDF http://www.setasign.de/products/pdf-php-solutions/fpdi/
it enables fpdf to import existing pdf files, though I'm not sure how can one replace links.
I'd say your best shot would be to generate the whole thing in php, or just save it in html, replace links in html, then convert html to pdf.
Without using the Adobe LiveCycle Designer, the easiest way to generate a custom PDF is to use an FDF file. There are tons of ways to do this, one of which is to download binaries from Adobe and install them on your server. But none of that is really needed. All you need is a pdf with fillable forms and a simple script that makes and FDF file. The FDF simply holds the data that needs to be filled in and a pointer to the pdf file to be filled in. I use this for our timesheets at work. The data goes into a web form, but must come out static and ugly and using a paper from from 30 years ago. Here's what your fdf file will look like (both with code and raw):
$file = "http://www.example.com/blankpdfform.pdf";
$data = "%FDF-1.2\n%âãÏÓ\n1 0 obj\n<< \n/FDF << /Fields [ ";
foreach($datafields as $field => $val) {
$data.='<< /T ('.$field.') /V ('.trim($val).')>> ';
}
$data.="] \n/F (".$file.") /ID [ <".md5(time()).">\n] >>".
" \n>> \nendobj\ntrailer\n".
"<<\n/Root 1 0 R \n\n>>\n%%EOF\n";
The end result being:
%FDF-1.2\n%âãÏÓ\n1 0 obj\n<< \n/FDF << /Fields [<< /T (email) /V (email#address.com)>>
/F ("http://www.example.com/blankpdfform.pdf") /ID [ <"SomeUniqueID">
] >> \nendobj\ntrailer<<
/Root 1 0 R
>>
%%EOF
If you have the PDF template with the email token stored in a file on the webserver, you can do this fairly easily. First you need to read in the file using PHP. You can do this using the file_get_contents method. Then use str_replace to replace the email token with the actual email. Finally, serve the file with the correct content-type.
$pdf = file_get_contents( 'template.pdf' );
$pdf = str_replace( '__EMAIL__TEMPLATE__', $userEmail, $pdf );
header( 'Content-type: application/pdf' );
print $pdf;
Doc links:
http://ca2.php.net/manual/en/function.file-get-contents.php
http://ca2.php.net/manual/en/function.str-replace.php
(I haven't actually tried this and you may run into some issues since PDF is a binary format, but in theory it should work...)
Related
I am extracting text from PDF files. this is the code:
<?php
require("PdfToText.php");
$file = 'SamplePF' ;
$pdf = new PdfToText ( "$file.pdf" ) ;
echo ( $pdf -> Text ) ;
?>
This class work fine for some PDF files.
The problem with this class is :
for some PDF files it take text from random page/line not in the
page sequence wise.
for some PDF files it is not showing any result.
for some PDF files it extract only one or two lines.
Please suggest some solution. Thank You!
I am not sure that this might be the exact problem because of which you are not able to extract but I also encountered something similar when extracting data from pdf. Sometimes the PDF files are locked by owner passwords which puts certain restrictions on the document and does not allow changing, content copying or extraction etc so as to protect its copyright issues. Check this link for more info on owner passwords.
So you can first try to remove owner password and then try to extract such pdf's. To remove owner passwords there are a number of tools available online, you can choose whichever fits you the best.
For a few years starting back in 2005 or so I was looking for a way to use php to populate a pre-existing pdf document, as redrawing an existing pdf from scratch in php to have the exact same look as an existing pdf is one heluva task, esp when it comes to ever changing federal BK docs.
After an eternal search, I found this code in 2008, which 'works', but is unreliable, in the sense that it may not 'find' the fdf file (which has to be dropped into the awaiting pdf) so the user has to try a few times, the fdf loads into the browser cache and the thing finally fires:
$tstamp = date('mdYHis');
$test1 = mysql_real_escape_string($_POST['test1']);
$test2 = mysql_real_escape_string($_POST['test2']);
$fdf=dirname(__FILE__).'/doc_test/'.$tstamp.'.fdf';
if (file_exists($fdf)) {unlink($fdf);}
require_once 'createFDF_doc_test.php';
$pdf_file_doc_test=$link. '/forms/doc_test.pdf';
// allow for up to 25 different files to be created, based on the minute
$min=date('i') % 25;
$fdf_file_dt=dirname(__FILE__).'/doc_test/'.$tstamp.'.fdf';
if(isset($_POST['test1'])){
$_POST['test1']=$_POST['test1'];
// get the FDF file contents
$fdf_doc_test=createFDF_doc_test($pdf_file_doc_test,$_POST);
// Create a file for later use
if($fp=fopen($fdf_file_dt,'w')){
fwrite($fp,$fdf_doc_test,strlen($fdf_doc_test));
$CREATED=TRUE;
}else{
echo 'Unable to create file: '.$fdf_file_dt.'<br><br>';
$CREATED=FALSE;
}
fclose($fp);
}
Here are the contents of createFDF_doc_test.php:
<?php
function createFDF_doc_test($file,$info){
$data="%FDF-1.2\n%âãÏÓ\n1 0 obj\n<< \n/FDF << /Fields [ ";
foreach($info as $field => $val){
if(is_array($val)){
$data.='<</T('.$field.')/V[';
foreach($val as $opt)
$data.='('.trim($opt).')';
$data.=']>>';
}else{
$data.='<</T('.$field.')/V('.trim($val).')>>';
}
}
$data.="] \n/F (".$file.") /ID [ <".md5(time()).">\n] >>".
" \n>> \nendobj\ntrailer\n".
"<<\n/Root 1 0 R \n\n>>\n%%EOF\n";
return $data;
}
?>
What all this does is creates an fdf file and stores it in a folder on the server. The field names from a html form are matched with the pdf and the fdf acts as the conduit between the two.
The content of the fdf, which is always successfully saved to the server, will look something like this:
%FDF-1.2
%âãÏÓ
1 0 obj
<<
/FDF << /Fields [ <</T(test1)/V(Test)>><</T(test2)/V(Complete)>>]
/F (http://example.com/forms/doc_test.pdf) /ID [ <5d721ab873727ae4de3ebd21859bbc60>
] >>
>>
endobj
trailer
<<
/Root 1 0 R
>>
%%EOF
The issue is the 'marriage' between the fdf and the pdf often doesn't fire because of some browser issue, or the timing the fdf is called, or something. Either way, the code is old, and I was hoping someone knew of a better, more efficient code that can quickly and buglessly move html form data, via php, into an awaiting pdf doc. I have been using the above for 8 years and I am tired of it.
We've been rebuilding our templating engine for generating reports based on user provided templates.
After scouring the web for solutions a combination of pdftk + https://github.com/mikehaertl/php-pdftk rose as the best solution.
It has a very easy interface that enables populating pdf form using php arrays also has a good UTF8 support.
As seen in the documentation the simplest use case is:
use mikehaertl\pdftk\Pdf;
// Fill form with data array
$pdf = new Pdf('form.pdf');
$pdf->fillForm(array('name'=>'ÄÜÖ äüö мирано čárka'))
->needAppearances()
->saveAs('filled.pdf');
// Fill form from FDF
$pdf = new Pdf('form.pdf');
$pdf->fillForm('data.fdf')
->saveAs('filled.pdf');
I'm aware that this is not a help for the present problem, but believe this will give a more maintainable code.
But the real fun starts if you want to embed pictures, we had to resort to a helper python script to calculate the position of elements that we want to attach picture.
I have a web form that uses an HTML5 canvas element to allow users to sign their name. When the form is submitted, all field values and the base64 string (e.g. "data:image/png;base64,blahblahetc") containing the user's signature are processed and stored.
I'd like to fill my pdf template with the submitted data and write the signature to the form but I am struggling with the signature task.
I found one technique while researching that suggests I could write the signature as a pdf button using:
<< /T (button1)/APRef << /N << /F (http://www.yoursite.com/pfds/icons.pdf)/Name (icon3)>> >> >>
However, I can't manage to get this to work. I don't know if the signature must be prepared as .png, .pdf, or something else. (I can successfully generate a .png on the server, but haven't tried to apply it to the .pdf because I don't know if I need it.)
I am using pdftk to fill my template .pdf with the dynamic .fdf file. Do I need to perform any special preparations on the signature button? I think I read something about setting the Layout to "Icon Only."
Since I could not find a way to apply the signature to the pdf as a button, I had to fiddle and hack to get all form data and signatures from the server onto a new pdf.
First fopen/fwrite the form values to new fdf, then use pdftk to generate an unsigned pdf:
echo exec("cd $submissions_path/; $pdftk \"$template\" fill_form \"$fdf\" output \"$unsigned_pdf\"; chmod 777 \"$unsigned_pdf\";");
Then fopen/fwrite my base64 signatures to signature images:
$fp=fopen("$submissions_path/$simg","wb");
fwrite($fp,base64_decode($scode));
fclose($fp);
Then generate an .html watermark to be converted to a watermark .pdf using mPDF (please excuse the use of tables, mPDF didn't like my <div>'s):
$watermark_pdf="InstallOrder_{$submissionID}_Watermark.pdf";
$watermark_html="<table style=\"width:792px;height:1123px;\"><tr>";
$watermark_html.="<td colspan=\"2\" style=\"padding-top:900px;padding-left:70px;width:240px;height:20px;\">{$watermark[CustomerSignature]}</td>";
$watermark_html.="</tr><tr>";
$watermark_html.="<td style=\"padding-top:16px;padding-left:69px;width:240px;height:20px;\">{$watermark[OwnerSignature]}</td>";
$watermark_html.="<td style=\"padding-top:16px;padding-left:169px;width:240px;height:20px;\">{$watermark[ManagerSignature]}</td>";
$watermark_html.="</tr></table>";
include("../mpdf/mpdf.php"); //Include mPDF Class
$mpdf=new mPDF('','',0,'',0,0,0,0,0,0,'P'); // Create new mPDF Document
$mpdf->WriteHTML($watermark_html);
$mpdf->Output("$watermark_pdf","F"); //save file to server - may include a path
Finally, stamp the watermark.pdf onto the unsigned.pdf using pdftk again:
echo exec("cd $submissions_path/; $pdftk \"$unsigned_pdf\" stamp \"$watermark_pdf\" output \"$pdf\"");
The most tedious part is correctly setting the size and position of the signature images on the watermark html.
I am converting a classic ASP application to PHP.
In the Classic ASP app, we are programatically populating fields that have been created in PDF documents using a component called ASPpdf.
I need to reproduce this behavior in PHP, but need to know if PHP can populate PDF fields on its own or if any third party plug in is needed.
Is this functionlity posible in PHP with or without a plug in?
Thanks.
Note: I already have the PDFs created, I do not need to create the actual PDF. I need to grab a preexisting PDF with form fields, populate those form fields and then save that custom PDF.
This is the first google search result I got, is there a reason this doesn't work for you?
http://koivi.com/fill-pdf-form-fields/tutorial.php
UPDATE
After reading a little further, this generates an FDF (which Acrobat can read). To generate an actual PDF you'll need to use this: http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
The resolution to my problem was to use the same COM component I used in Classic ASP in my new PHP apps. The COM object give me tremendous control over PDF documents.
The component I use is AspPdf
<?php
$pdf = new COM("Persits.Pdf") or die("Unable to instantiate Word");
$pdfdoc = $pdf->OpenDocument( "pdf.pdf" );
$pdffont = $pdfdoc->Fonts("Helvetica-Bold");
$pdfdoc->Form->RemoveXFA();
$pdffield = $pdfdoc->Form->FindField("FirstName");
$pdffield->SetFieldValue("PHP Text", $pdffont);
$pdffile = $pdfdoc->save( "php.pdf" , false);
echo $pdf->version;
$pdf = null;
?>
It looks as though the pdftk PDF toolkit may be able to do this. Reading the manual:
fill_form < FDF data filename | XFDF data filename | - | PROMPT >
Fills the single input PDF’s form fields with the data from an FDF file, XFDF file or stdin. Enter the data filename after fill_form, or use - to pass the data via stdin, like so:
pdftk form.pdf fill_form data.fdf output form.filled.pdf
Is it possible to merge FDF data with a PDF file using PHP alone? Or is there no option but to use a 3rd party command line tool to achieve this?
If that is the case can someone point me in the direction of one?
I am currently outputting the FDF file to the browser in the hope that it will redirect the user to the filled in PDF but for some people that is not the case. The FDF contents is being output to the screen, even though I am using header('Content-type: application/vnd.fdf');
For future reference, it looks like there isn't a reliable way of doing it without a 3rd party app. Pdftk (http://www.accesspdf.com/pdftk/) ended up being my solution.
I first generated the FDF file as before, and then merged it into my PDF file using the following PHP code
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="Download.pdf"');
passthru("pdftk file.pdf fill_form data.fdf output - ");
exit;
It was much easier than I thought it would be. This instantly eliminates the need to hack around with headers and file extensions to ensure all browsers handle an FDF properly, as it simply makes the browser download the PDF file.
If you want the PDF output file to no longer be editable, use
passthru("pdftk file.pdf fill_form data.fdf output - flatten");
Apologies if this is basic stuff, just thought I'd put it all in one place so that people don't go through the headache that I endured.
N.B. If your PATH variable is not set, you will need to use the full path to pdftk i.e.
passthru("/usr/local/bin/pdftk file.pdf fill_form data.fdf output - flatten");
There is another way to day that not using passthru nor pdftk but just a script made in 2004 but still working well : forge_fdf
it helps you to build a fdf that you can incoporate straithly in your pdf, it means that you
Save this in a php file, let's say generatePdf.php
require_once('forge_fdf.php');
// leave this blank if we're associating the FDF w/ the PDF via URL
$pdf_form_url= "";
// default data; these two arrays must ultimately list all of the fields
// you desire to alter, even if you just want to set the 'hidden' flag;
//
//
$fdf_data_names= array(); // none of these in this example
$fdf_data_strings= array(); // none of these in this example
$fdf_data_strings['email']=mb_strtolower($row_delivreur['firstname']).'.'.mb_strtolower($row_delivreur['lastname']).'#gmail.com';
$fields_hidden= array();
$fields_readonly= array();
// set this to retry the previous state
$retry_b= false;
header( 'content-type: application/vnd.fdf' );
echo forge_fdf( $pdf_form_url,
$fdf_data_strings,
$fdf_data_names,
$fields_hidden,
$fields_readonly );
Making a link to Pathtoyourpdf/nameofpdffile.pdf#FDF=generatePdf.php will open your PDF file in browser (alternatively there is a way to save it to disk i think i remember) and the field email will be filled with data from MYSQL : mb_strtolower($row_delivreur['firstname']).'.'.mb_strtolower($row_delivreur['lastname']).'#gmail.com'
It works with checkboxes, radio button,... It opens well in firefox, it has to be tested with other browsers.
More infos on PDF HACKS
by far the easiest way I have found to install pdftk on centos:
Install rpmforge repo - http://wiki.centos.org/AdditionalResources/Repositories/RPMForge#head-5aabf02717d5b6b12d47edbc5811404998926a1b
then
yum install pdftk
and thats it!
http://www.setasign.de/products/pdf-php-solutions/fpdi/demos/concatenate-fake/
This works , the classes download are linked to from the web site too,
It requires no passthru/exec command and no additional extensions.
Edited to say, this doesn't work with newer pdf versions 1.5+, reverted to PDFTK, fiddly but works with all pdfs using the 'exec' command.