Acoording this thread I have a similar problem:
Only first pdf file filled with fpdm can be opened
With FPDM (https://github.com/codeshell/fpdm) even with the latest fix (https://gist.github.com/josh-candybox/173cacc476631720a05879327950da4e) I just can't get multiple pdf files processing. One file only. It is not header related, since the files are being thrown out as files (not as downloads).
See me code. One suggested to do the loop with an ajax call. If this is really the only way, how can I do that? I even try to reset the object/class. It just doesn't care...
Error msg: FPDF-Merge Error: getFilter cannot open stream of object
because filter '' is not supported, sorry.
$j=1;
foreach ($id as $value => $key) {
if ($value == 'adresse') {
echo $value." -> ".nl2br($key)."<br>\n";
$fields = array(
'adresse1' => $key
);
$pdf = NULL;
$pdf = new FPDM(__DIR__.'/fpdm/dmc3fixed.pdf' );
$pdf->Load($fields, true);
$pdf->Merge();
$filename=__DIR__."/fpdm/dmc".$j.".pdf";
$pdf->Output($filename,'F');
$pdf->closeFile();
unset($pdf);
$pdf = NULL;
$j++;
} else { ... }
P.S.: Kind of workaround, but doesn't answer my question:
So, if anyone of you has the same problem, actually I managed to accomplish generating multiple PDFs with dynamic text. In my case I wanted to put addresses to letter templates. So I made a PDF Form with a multi cell. I ended up just printing the address with FPDF and FPDI, so... here you go:
require_once __DIR__ . DIRECTORY_SEPARATOR .'fpdi'.DIRECTORY_SEPARATOR.'autoload.php';
require_once(__DIR__ . DIRECTORY_SEPARATOR .'fpdf'.DIRECTORY_SEPARATOR.'fpdf.php');
require_once(__DIR__ . DIRECTORY_SEPARATOR .'fpdi'.DIRECTORY_SEPARATOR.'fpdi.php');
use setasign\Fpdi\Fpdi;
$pdf = null;
$i = 1;
foreach ($result as $value => $key) {
$pdf = new FPDI();
$pagecount = $pdf->setSourceFile(__DIR__ . DIRECTORY_SEPARATOR.'template.pdf');
for ($n = 1; $n <= $pagecount; $n++) {
$pdf->AddPage();
$tplIdx = $pdf->importPage($n);
$pdf->useTemplate($tplIdx);
$pdf->SetFont('Arial', '', 11);
$pdf->SetXY(25, 60);
$pdf->MultiCell(80, 5, $address);
$pdf->Output(__DIR__ . DIRECTORY_SEPARATOR."output".$i.".PDF", "F");
$pdf = NULL;
$i++;
}
}
Related
I have a problem by including a pdf merge system
I have tried a lot of code from git, but nothing works.
Now I have seen that if I comment out the lines with the use:
than the page can load if the use lines are in the code the page will not load.
if (isset($_POST["merge"]))
{
//use setasign\Fpdi;
//use setasign\fpdf;
require_once '../buchhaltung/vendor/autoload.php';
require_once '../buchhaltung/vendor/setasign/fpdf/fpdf.php';
error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit(2);
date_default_timezone_set('UTC');
$start = microtime(true);
$pdf = new Fpdi\Fpdi();
//$pdf = new Fpdi\TcpdfFpdi('L', 'mm', 'A3');
if ($pdf instanceof \TCPDF) {
$pdf->SetProtection(['print'], '', 'owner');
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
}
$files = [
' $_SESSION["filePath0"]',
' $_SESSION["filePath1"]',
];
foreach ($files as $file) {
$pageCount = $pdf->setSourceFile($file);
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
$pdf->AddPage();
$pageId = $pdf->importPage($pageNo, '/MediaBox');
//$pageId = $pdf->importPage($pageNo, Fpdi\PdfReader\PageBoundaries::ART_BOX);
$s = $pdf->useTemplate($pageId, 10, 10, 200);
}
}
$file = uniqid().'.pdf';
$pdf->Output('I', 'simple.pdf');
//$pdf->Output('output/'.$file, 'I');
}
But if I comment this lines out I get this fault:
Fatal error: Uncaught Error: Class "Fpdi\Fpdi" not found in /home/.sites/707/site3898181/web/buchhaltung/belegAdd.php:28 Stack trace: #0 {main} thrown in /home/.sites/707/site3898181/web/buchhaltung/belegAdd.php on line 28
Does someone have an idea what I am doing wrong?
The function of the Page should :
Upload multiple pdf files to the ftp (work)
if upload more than one file -> merge to one file and last store the path of the file into DB (this part I have in a other file (copy and paste))
only the merge does not work
I am using PDFTOHTML (a php library) to convert pdf files to html and it's working fine but it's showing converted file in a browser and not storing in local folder, i want to store converted html in local folder using php with the same name as pdf was i-e mydata.pdf to mydata.html
Code that is converting pdf to html is:-
<?php
// if you are using composer, just use this
include 'vendor/autoload.php';
$pdf = new \TonchikTm\PdfToHtml\Pdf('cv.pdf', [
'pdftohtml_path' => 'C:/wamp64/www/new/poppler-0.51/bin/pdftohtml.exe',
'pdfinfo_path' => 'C:/wamp64/www/new/poppler-0.51/bin/pdfinfo.exe'
]);
// get content from all pages and loop for they
foreach ($pdf->getHtml()->getAllPages() as $page) {
echo $page . '<br/>';
}
?>
Just change your foreach to
$filePdf = 'cv'; // your pdf filename without extension
$pdf = new \TonchikTm\PdfToHtml\Pdf($filePdf.'.pdf', [
'pdftohtml_path' => 'C:/wamp64/www/new/poppler-0.51/bin/pdftohtml.exe',
'pdfinfo_path' => 'C:/wamp64/www/new/poppler-0.51/bin/pdfinfo.exe'
]);
$counterPage = 1;
foreach ($pdf->getHtml()->getAllPages() as $page) {
$filename = $filePdf . "_" . $counterPage.'.html'; // set as string directory and filename where you want to save it
if (file_exists($filename)) {
// if file exist do something
} else {
// else
$fileOpen = fopen($filename, 'w+');
fputs($fileOpen, $page);
fclose($fileOpen);
}
$counterPage++;
echo $page . '<br/>';
}
This will create you file for example: example_1.html, example_2.html and so on.
if this not help you then probably you need to use file_put_contents with ob_start() and ob_get_contents() read more here
Look this :
<?php
// if you are using composer, just use this
include 'vendor/autoload.php';
$pdf = new \TonchikTm\PdfToHtml\Pdf('cv.pdf', ['pdftohtml_path' => 'C:/wamp64/www/new/poppler-0.51/bin/pdftohtml.exe', 'pdfinfo_path' => 'C:/wamp64/www/new/poppler-0.51/bin/pdfinfo.exe']);
// get content from all pages and loop for they
$file = fopen('cv.html', 'w+');
$data = null;
foreach ($pdf->getHtml()->getAllPages() as $page) {
$data .= "".$page."<br/>";
}
fputs($file, $data);
fclose($file);
I did not test this code
I've written the following code for merging PDFs using this answer
function merge_pdfs() {
$pdfs_array = array('1.pdf', '2.pdf');
$pdf = new FPDI_Protection();
for ($i = 0; $i < count($pdfs_array); $i++ ) {
$pagecount = $pdf->setSourceFile($pdfs_array[$i]);
for($j = 0; $j < $pagecount ; $j++) {
$tplidx = $pdf->importPage(($j +1), '/MediaBox');
$pdf->addPage('P','A4');
$pdf->useTemplate($tplidx, 0, 0, 0, 0, TRUE);
}
}
$dt = new DateTime(NULL, new DateTimeZone($data->user->timezone));
$pdf->SetTitle('PDF, created: '.$dt->format(MYHMRS_DATETIME_FRIENDLY));
$pdf->SetSubject('PDF subject !');
$output = $pdf->Output('', 'S');
$name = "PDF".'-'.$dt->format('ymd').'.pdf';
$this->output
->set_header("Content-Disposition: filename=$name;")
->set_content_type('Application/pdf')
->set_output($output);
}
So, after this I'm getting the following error message
This document (1.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)
I've checked the link and it suggests to set another PDF Parser ( If I understand right )
But I'm not sure how to make it working with Codeigniter and my example
Should I create library and try to use it?
Or maybe you know another solution for merging PDFs
The issue was related to PDF versions
Edit
If you don't know, the PDFs has versions. Yeah, I was surprised as well. Please check them here PDF versions
So, the problem was that I was trying to merge PDF 1.5 version with PDF 1.6
An example. It is simple.
<?php
require_once __DIR__ . '/vendor/autoload.php';
$mpdf = new \Mpdf\Mpdf();
$mpdf->WriteHTML('<h1>Hello world!</h1>');
$mpdf->AddPage('P');
$mpdf->WriteHTML('<h1>More</h1>');
$mpdf->Output();
?>
i was splitting pdf into different single page using fpdf and fpdi. Everything works fine but the link inside pdf was not working. Link was removed on splitted single pages.
split_pdf("test.pdf", 'splitedpdf/');
function split_pdf($filename, $end_directory = false)
{
require_once('fpdf/fpdf.php');
require_once('fpdi/fpdi.php');
$end_directory = $end_directory ? $end_directory : './';
$new_path = preg_replace('/[\/]+/', '/', $end_directory.'/'.substr($filename, 0, strrpos($filename, '/')));
if (!is_dir($new_path))
{
// Will make directories under end directory that don't exist
// Provided that end directory exists and has the right permissions
mkdir($new_path, 0777, true);
}
$pdf = new FPDI();
$pagecount = $pdf->setSourceFile($filename); // How many pages?
// Split each page into a new PDF
for ($i = 1; $i <= $pagecount; $i++) {
$new_pdf = new FPDI();
$new_pdf->AddPage();
$new_pdf->setSourceFile($filename);
$new_pdf->useTemplate($new_pdf->importPage($i));
try {
$new_filename = $end_directory.str_replace('.pdf', '', $filename).'_'.$i.".pdf";
$new_pdf->Output($new_filename, "F");
echo "Page ".$i." split into ".$new_filename."<br />\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
}
// $pdf->close();
}
FPDI is not able to handle any dynamic content link links, form fields or any other annotation type. There's an extension which support at least links (only compatible with FPDI 1.4.4 + FPDF_TPL 1.2.3).
If you need to extract the pages including all attached annotations, you may check out the SetaPDF-Merger component (not free!).
I am using the PHP libraries TCPDF and FPDI to combine PDF documents, and am getting the following error:
TCPDF ERROR: Unable to find object (10, 0) at expected location
I have the commercial version of FPDI.
It appears that the issue is only happening with PDF Version 1.3 (Acrobat 4.x) files. Here is a screenshot of a file's document properties that is creating the error. http://imagebin.org/215041
I'd like to skip over any files with errors instead of letting the script die. I have modified the error handling with a new class ErrorIgnoringTCPDF, however, it is not working.
Any ideas?
require_once('../../libraries/tcpdf/tcpdf.php');
require_once('../../libraries/fpdi/fpdi.php');
class ErrorIgnoringTCPDF extends FPDI {
public function Error($msg) {
// unset all class variables
$this->_destroy(true);
// exit program and print error
//die('<strong>TCPDF ERROR: </strong>'.$msg);
}
}
$pdf = new ErrorIgnoringTCPDF();
$pdf->setPrintHeader(false);
$prows = fetch_data($id);
foreach ($prows AS $row) {
$irows = get_imaged_docs($row['pat_id']);
foreach($irows AS $irow){
if ($irow['type'] === 'application/pdf'){
$doc_id = $irow['id'];
$content = get_pdf_imaged_docs($doc_id);
$pagecount = $pdf->setSourceFile($content);
for ($i = 1; $i <= $pagecount; $i++) {
$tplidx = $pdf->ImportPage($i);
$s = $pdf->getTemplatesize($tplidx);
$pdf->AddPage('P', array($s['w'], $s['h']));
$pdf->useTemplate($tplidx);
}
} else {
$pdf->AddPage();
$doc = fetch_document_content($irow['id'], $irow['filename']);
$img = base64_encode($doc);
$imgdata = base64_decode($img);
$pdf->Image('#'.$imgdata);
}
}
}
$pdf->Output('documents.pdf', 'D');
If you are using Linux you can use shell_exec to combine files
function combine_pdf($outputName,$fileArray)
{
$cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=$outputName ";
foreach($fileArray as $file)
{
$cmd .= $file." ";
}
$result = shell_exec($cmd);
}
Have you tried just suppressing the error?
$pagecount = #$pdf->setSourceFile($content);
if (empty($pagecount))
continue; // or whatever you want to do, maybe set $is_invalid = true;
This simply indicates that the PDF document is errorious. It points to a specific byte offset position where the expected object is not found.
I wont say this is an appropriate/best fix, but it may resolve your problem,
In: pdf_parser.php, comment out the line:
$this->error("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location");
It should be near line 544.
You'll also likely need to replace:
if (!is_array($kids))
$this->error('Cannot find /Kids in current /Page-Dictionary');
with:
if (!is_array($kids)){
// $this->error('Cannot find /Kids in current /Page-Dictionary');
return;
}
in the fpdi_pdf_parser.php file
Hope that helps. It worked for me.
I have the same problem and i am using this code to fix my problems.
class convertPDF extends FPDI {
public function error($msg) {
throw new Exception($msg);
}
...other stuff...
}
try {
$convertPdf = new convertPDF();
} catch(Exception $e) {
die($e->getMessage);
}
This answer is for people who search for this problem. Have luck!