FPDI free pdf parser that support PDF above 1.4
15
up 15 down 1
starvotestarvotestarvotestarvotestarvote
Thank you for voting !

FPDI free pdf parser that support PDF above 1.4

One of our client asked a very interesting question –

Is there any trick for FPDI free Pdf parser to make it compatible with PDF version higher than 1.4 without purchasing the commercial license?

Starting from the introduction of FDPI , it’s a collection of PHP classes allowing developers to read pages from PDF files & use them as templates in FPDF package, which was developed by Olivier Plathey. Apart from a copy of FPDF, FPDI doesn’t require any special PHP extensions. For encrypting PDF files FDPI with FDPF and FDPI-protection package is required.

Directly coming to the point, FPDI free pdf-parser can “only” handle PDF documents up to PDF version 1.4. With PDF version 1.5 there were new compression features introduced which involve changes in internal structure of a PDF document. Commercial version of FPDI PDF-parser supporting PDF document above 1.4 is available at Setasign but as said its commercial paid version. Many developers want to Encrypt PDF files (version above 1.4) using free FPDI PDF parser but the free package doesn’t support it & display one of the following error messages –

PHP Fatal error: Unable to find xref table - Maybe a Problem with 'auto_detect_line_endings

PHP Fatal error: Uncaught exception 'Exception' with message 'This document (/tmp/document.pdf) probably uses a compression technique which is not supported by the free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)' in /FPDI-1.5.2/pdf_parser.php:329

[... 11:01:06 2015] [error] [client 333.333.333.333] PHP Fatal error:
Uncaught exception 'Exception' with message 'This document (/tmp/label_55a780e22172f.pdf) probably uses a compression technique which is not supported by the free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)' in
...lib/FPDI-1.5.2/pdf_parser.php:329
Stack trace:
#0 ...lib/FPDI-1.5.2/pdf_parser.php(202): pdf_parser->_readXref(Array, 87345)
#1 ...lib/FPDI-1.5.2/fpdi_pdf_parser.php(71): pdf_parser->__construct('/tmp/...')
#2 ...lib/FPDI-1.5.2/fpdi.php(128): fpdi_pdf_parser->__construct('/tmp/..')
#3 ...lib/FPDI-1.5.2/fpdi.php(108): FPDI->_getPdfParser('/tmp/...')
#4 ...php/utils/concatpdf.class.php(37): FPDI->setSourceFile('/tmp/...')
#5 ...php/utils/shipping/provider in ...lib/FPDI-1.5.2/pdf_parser.php on line 329

Indeed getting a code trick and making a free tool compatible for our premium need is much better idea than buying a commercial version of tool. Think like a real smart developer and you will get the code idea of what you want to get done.

Indeed , the simplest way is to convert the PDF file version before it is submitted to FDPI pdf parser. we need to first check the PDF file version with a PHP code.


// pdf version information
$filepdf = fopen("document.pdf","r");
if ($filepdf) {
$line_first = fgets($filepdf);
fclose($filepdf);
} else{
echo "error opening the file.";
}

PDF file version is mostly present in first line of PDF. so we need to read the first line of PDF which will give us something like below response stored in a variable $line_first when using above PHP code –

%PDF-1.5%

Here we get the PDF version but we need to separate version number(1.5) from complete line %PDF-1.5%. so extracting the number from variable $line_first and storing the numeric value in variable $pdfversion using below code.


// extract number such as 1.4 ,1.5 from first read line of pdf file
preg_match_all('!\d+!', $line_first, $matches);	
// save that number in a variable
$pdfversion = implode('.', $matches[0]);

we need to now compare the PDF version of submitted file from 1.4 in such away that if value of variable $pdfversion is greater than 1.4 than proceed with if condition otherwise proceed with else condition.


<?php
if($pdfversion > "1.4"){
// proceed if PDF version greater than 1.4
// convert with ghostscript to version 1.4
// continue with FPDI + FDPF + FDPI PROTECTION
}
else{
// proceed if PDF version upto 1.4
// continue with FPDI + FDPF + FDPI PROTECTION
}
?>

Here we get the PDF version in “only” numeric value stored in a variable/string , as we know very well that free PDF parser only support PDF file upto version 1.4 , so now its time to implement the main logic of converting our PDF file(version above 1.4) into PDF version 1.4 using GHOSTSCRIPT command line. Please make sure that GHOSTSCRIPT is already installed on your server.

use the below command line GHOSTSCRIPT code under PHP exec()


// USE GHOSTSCRIPT IF PDF VERSION ABOVE 1.4 AND SAVE ANY PDF TO VERSION 1.4 , SAVE NEW PDF OF 1.4 VERSION TO NEW LOCATION 
<?php
exec('gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="'.$srcfile_new.'" "'.$srcfile.'"'); 
?>

Example Code:


<?php
// Report all errors
error_reporting(E_ALL);
ini_set('display_errors', true);

  // Generate random number and store in $random variable
  $random = rand(1,10000);

  // get pdf file name, send name from ajax on other side and received here 
  $filename = $_POST['filenamepdf'];

  // compete path of pdf file including directory name
  $srcfile = 'pdf-uploaded/'.$filename;
		
  // new path of new pdf file created by ghostscript if file above 1.4 
  $srcfile_new = 'pdf-compatible/'.$filename;
		
  // path of saved encrypted pdf file by fdpi
  $dest_file = 'pdf-encrypted/encrypted-'.$random.'.pdf';
                     
  // read pdf file first line because pdf first line contains pdf version information
  $filepdf = fopen($srcfile,"r");
   if($filepdf) {
     $line_first = fgets($filepdf);
     fclose($filepdf);
   }
   else{
     echo "error opening the file.";
   }
  // extract number such as 1.4,1.5 from first read line of pdf file
  preg_match_all('!\d+!', $line_first, $matches);
					 
  // save that number in a variable
  $pdfversion = implode('.', $matches[0]);

  // compare that number from 1.4(if greater than proceed with ghostscript)
  if($pdfversion > "1.4"){
  // USE GHOSTSCRIPT IF PDF VERSION ABOVE 1.4 AND SAVE ANY PDF TO VERSION 1.4 , SAVE NEW PDF OF 1.4 VERSION TO NEW PATH
    shell_exec('gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="'.$srcfile_new.'" "'.$srcfile.'"'); 

    // use now fpdi with pdf parser and fpdi protection
    require_once('fpdi/FPDI_Protection.php');
    $pdf = new \FPDI_Protection();
    $pagecount = $pdf->setSourceFile($srcfile_new);

    for ($loop = 1; $loop <= $pagecount; $loop++) {
      $tplidx = $pdf->importPage($loop);
      $pdf->addPage();
      $pdf->useTemplate($tplidx);
    }

    $pdf->SetProtection(\FPDI_Protection::FULL_PERMISSIONS, "password");
    //$pdf->SetProtection(\FPDI_Protection::FULL_PERMISSIONS, '123456', 'ABCDEF');
    $pdf->Output($dest_file, 'F');
         
  }
  else{						 
    // use FPDI if pdf version upto 1.4 no need for ghostscript 
    require_once('fpdi/FPDI_Protection.php');
    $pdf = new \FPDI_Protection();
    $pagecount = $pdf->setSourceFile($srcfile);

    for ($loop = 1; $loop <= $pagecount; $loop++) {
       $tplidx = $pdf->importPage($loop);
       $pdf->addPage();
       $pdf->useTemplate($tplidx);
     }

    $pdf->SetProtection(\FPDI_Protection::FULL_PERMISSIONS, "password");
    //$pdf->SetProtection(\FPDI_Protection::FULL_PERMISSIONS, '123456', 'ABCDEF');
    $pdf->Output($dest_file, 'F');
  }                
?>

Generate the download link for source code(package Includes FPDI + FPDI-protection + FDPF) & Encrypt any version of PDF file. The generated link will get expired in 1 hour. Once expired, you need to re-generate the download link.

Generate Download link

Subscribe now for new blog notifications and always stay connected with us. please click here

15 thoughts on “FPDI free pdf parser that support PDF above 1.4”

  • Thanks for sharing, the information came in very useful in a small project I am working on. 🙂


    Comment by Jason on
    • Jason , thank you too for your positive comment. Myself shoaib and Let me know anytime if I can help you for your any project issue. you can contact me anytime via email / skype.


      Comment by webnius_admin on
    • muyideen mohammed , it was a server fault and we have fixed it. The download link has started working. you can please try downloading the source code now.


      Comment by webnius_admin on
  • thank you for sharing your trick !


    Comment by jérome on
  • Nice trick! 🙂 but download link doesn’t work 🙁


    Comment by Patrick on
    • we have migrated the hosting & domain recently and the website back-end resources are on maintenance. That’s the reason download link doesn’t work. But its gonna work very soon. Thank you


      Comment by webnius_admin on
  • This is what I have been looking for!

    I will implement this and give you praise if it works. The code looks to make sense so I don’t doubt it will work


    Comment by Ste on
    • This has worked except I had to make 1 small change

      Add `-dCompatibilityLevel=1.4` as a Ghostscript parameter. EG – ‘gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -sOutputFile=”‘.$convertedPdfVersion.'” “‘.$fileLocation.'”‘


      Comment by Ste on
  • // function to uncompress a PDF if later than 1.4

    function uncompressPDF($infile, $outfile) {
    shell_exec(‘gs -dBATCH -dCompatibilityLevel=1.4 -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=”‘.$outfile.'” “‘.$infile.'”‘);
    return $outfile;
    }


    Comment by Steve on
  • Many thanks for sharing your trick to uncompress a PDF by GhostScript.

    That was very helpful.

    But to check the version of a PDF is not a save way to fix this problem, because some pdf-generators give back a version less than 1.5 but using features of compressing from the version 1.5 or later.

    To fix this problem is a more save way to put the command that produce the exception-error in a try- / catch-block.

    For example in my script to get the amount of pages:

    $pdf = new \setasign\Fpdi\Fpdi();
    $pdf->SetDisplayMode( 100 );
    try {
    $pages = $pdf->setSourceFile(“Document.pdf”);
    } catch (Exception $ex){
    $Tool = “gswin64c.exe -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=”‘Temp.pdf” “Document.pdf”‘;
    shell_exec($Tool);

    $pdf = new \setasign\Fpdi\Fpdi();
    $pdf->SetDisplayMode( 100 );
    $pages = $pdf->setSourceFile(“Temp.pdf”);
    }
    … proceed script …


    Comment by Bastian Blanc on
  • hi, I hv tried this tutorial, but i get some problem.
    InvalidArgumentException
    Invalid type in $file parameter (resource (closed))
    ==========================
    this is my code:
    if (!empty($file)) {
    if ($pdfversion > 1.4) {
    shell_exec(‘gs -dBATCH -dCompatibilityLevel=1.4 -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=”‘.$file2.'” “‘.$file.'”‘);
    echo $file.”;
    echo $file2;
    exit();
    $this->file = $file2;
    }else{
    $this->file = $file;
    }
    }

    and this the value when i echo the variable :
    $file -> C:\xampp\htdocs\digiKnow/public/storage/files\April2021\I1ygQlltigwwZd3QOfYL.pdf
    $file2 -> Resource id #640

    thanks in advance


    Comment by Saddam on
    • There can be few things you need to consider.
      1) Try to run the code on live server instead of local-host
      2) Check your PHP version. Test the code on PHP-5.6 and PHP 7.1 as well.
      3) Make sure you are using my code right way without mistakes. Copy the code exactly.


      Comment by infoconic_admin on
  • Hi!
    I found your code very useful.Thak you very much. I was looking for this solution for long!
    By the way, I´m struggling to download the code.
    Can you provide a better way to accomplish the download?
    Thanks is advance!


    Comment by Cássimo Braimo on
  • Warning: mysqli::__construct(): (HY000/1045): Access denied for user ‘infoconic_new’@’localhost’ (using password: YES) in /home/infotech/public_html/download-zips/generate-key.php on line 16
    Error database connectivity


    Comment by ArKa on

Leave a Reply to jérome Cancel reply

Your email address will not be published. Required fields are marked *

*