I am using Spatie\PdfToImage in my Symfony application to change PDFs into images. Here is the function I am using:
public function savePdfPreviewImage($fullFilePath, $thumbnailPath)
{
$pdf = new Pdf($fullFilePath);
$pdf->saveImage($thumbnailPath);
return $this;
}
When given a path to a PDF, the library returns this message:
An image could not be created from the given input
How can I go about finding a solution to this?
So far I have tried verifying with an ls that the file exists in the place where the app thinks it is. I have also tried opening the file -- which has a .pdf file extension -- in a PDF reader to verify that it is not corrupt. Neither of those two actions yielded any clues.
=====
Edit 1: I traced this message back to the Imagine.php file, where I removed an error-suppression line. That gave me this slightly less opaque message:
Warning: imagecreatefromstring(): Data is not in a recognized format
====
Edit 2: I have also verified that ghostscript is installed. The gs command is available from my server environment. I have also verified that the path provided for $thumbnailPath is a valid path/filename ending in .jpg.
I figured out what the problem was.
The conversion to PDF was actually behaving just fine. What was misbehaving was a later call within the application to the Imagine.php library, unsuccessfully resizing the image that my code successfully created. Here is the code that allowed me to see this:
public function savePdfPreviewImage($fullFilePath, $thumbnailPath)
{
//$pdf = new Pdf($fullFilePath);
//$pdf->saveImage($thumbnailPath); //This gives us "An image could not be created from the given input" and "Data is not in a recognized format"
//Let's try it with a manual call to GhostScript instead ...
exec(
'gs -o ' . //This creates the image successfully, but the error still shows up.
$thumbnailPath . //That means the error isn't coming from here, since we're no longer calling any external PHP libraries.
' -sDEVICE=jpeg ' .
$fullFilePath
);
return $this;
}
You do not need a lib for this, imagick alone will do fine.
$pdf = new \Imagick();
$pdf->setColorspace(\Imagick::COLORSPACE_SRGB);
$pdf->readImage($srcPath);
$pdf->setIteratorIndex($pageNo);
$pdf->writeImage($outPath);
(Imagick will recognize the file extension from $outPath)
Related
I'm trying to use FPDF and FPDI to edit a PDF and add text to it. I keep getting an "Incorrect output destination" error but the destination is the correct location that I want it to create a file in, why does FPDF not like my output destination?
This is in a laravel project
$pdf = new \setasign\Fpdi\Fpdi();
$pdf->AddPage();
$pdf->setSourceFile(public_path('/pdf/higher.pdf'));
$tplIdx = $pdf->importPage(1);
$pdf->useTemplate($tplIdx, 10, 10, 100);
$pdf->SetFont('Helvetica');
$pdf->SetTextColor(255, 0, 0);
$pdf->SetXY(30, 30);
$pdf->Write(0, 'This is just a simple text');
$pdf->Output(public_path('/pdf/'),'higher2');
return $pdf;
and the error is:
message: "FPDF error: Incorrect output destination: /home/vagrant/code/project-name/public/pdf/"
I've also tried removing the "public_path()" and just setting it to Output('pdf', 'higher2') and no good there either.
Furthermore I've also tried changing the name of the output pdf to higher2.pdf just in case it wanted to see the extension (but obviously it's having more of a problem with the destination and not the name)
I've even tried changing permissions on this folder to be writable by anyone:
drwxrwxrwx 5 ion staff 160 May 21 05:44 pdf
edit: Just to note I see that the method with the public_path() is trying to save to my vagrant folder for some reason, that's part of the reason I'm confused. When I try to save to '/pdf' without public_path(), I get this error:
message: "FPDF error: Incorrect output destination: /pdf/"
edit 2:
I've also tried this:
$pdf->Output('F','/pdf/higher2.pdf');
and got the error:
message: "file_put_contents(/pdf/higher2.pdf): failed to open stream: No such file or directory"
and also tried the original name of the pdf which definitely exists and got the same error:
$pdf->Output('F','/pdf/higher.pdf');
You should never overwrite the file you are reading from!
The signature of the Output() method is:
string Output([string dest [, string name [, boolean isUTF8]]])
The $dest parameter is defined as:
Destination where to send the document. It can be one of the following:
I: send the file inline to the browser. The PDF viewer is used if available.
D: send to the browser and force a file download with the name given by name.
F: save to a local file with the name given by name (may include a path).
S: return the document as a string.
The default value is I.
So your code:
$pdf->Output(public_path('/pdf/'),'higher2');
makes absolutely no sense. I guess you want to save the resulting PDF to the path in the public area with the name higher2.pdf. So your code should look like:
$pdf->Output('F', public_path('/pdf/higher2.pdf'));
PS: You cannot edit a PDF with FPDI!
The Output() method requires the first parameter to be the destination and the 2nd parameter the filename.
From the documentation:
F: save to a local file with the name given by name (may include a path).
Try this:
$filename="/pdf/higher2.pdf";
$pdf->Output($filename,'F');
For the FPDF package, the syntax $pdf->Output('F','/pdf/higher2.pdf'); is wrong and you need to adjust your call as Jan Slabon explained.
However, if you want to support UTF-8 characters, then you need the tFPDF package, which is also supported by the setasign vendor:
$pdf = new \setasign\Fpdi\Tfpdf\Fpdi();
For this package you can store the output like this:
$pdf->Output('/pdf/higher2.pdf');
I'm trying to upload a PDF document from a stage server to a remote location using $sftp-put();
CODE:
$sftp = new SFTP($config::SFTP_SERVER);
// login to remote server
if (!$sftp->login($config::SFTP_USER, $config::SFTP_PASSWORD)) {
throw new Exception('Login failed');
}
// move to relevant directory
$sftp->chdir('fatca');
// upload file
$uploadFile = $sftp->put('test-pdf-upload.pdf', '/srv/www/vhosts/stage.johno.com/fatca/src/uploads/pdfs/345-553453-434__05122017_16:45:26.pdf', NET_SFTP_LOCAL_FILE);
// Error checking for local env only
var_dump($uploadFile);
var_dump($sftp->getSFTPLog());
I'm expecting to view the same PDF, that contains user data and some user uploaded images. I've also confirmed that the original PDF has been created successfully on the staging server, it is intact and shows the relevant information.
The resulting file is created in the new remote server location however it is damaged/unreadable.
The output from var_dump($sftp->getSFTPLog()); is not encouraging either:
bool(false)
What am I doing wrong here? Feel like I've followed the phpseclib documentation well... Although its been one of those long, long days in front of the screen!
Any advice greatly appreciated as always.
You're using phpseclib 2.0. I can tell because you're doing new SFTP() instead of new Net_SFTP(). For 2.0 you need to do SFTP::SOURCE_LOCAL_FILE. eg.
$uploadFile =
$sftp->put(
'test-pdf-upload.pdf',
'/srv/www/vhosts/stage.johno.com/fatca/src/uploads/pdfs/345-553453-434__05122017_16:45:26.pdf',
SFTP::SOURCE_LOCAL_FILE);
I am creating .docx files from a template using PHPWord. It works fine but now I want to convert the generated file to PDF.
First I tried using tcpdf in combination with PHPWord
$wordPdf = \PhpOffice\PhpWord\IOFactory::load($filename.".docx");
\PhpOffice\PhpWord\Settings::setPdfRendererPath(dirname(__FILE__)."/../../Office/tcpdf");
\PhpOffice\PhpWord\Settings::setPdfRendererName('TCPDF');
$pdfWriter = \PhpOffice\PhpWord\IOFactory::createWriter($wordPdf , 'PDF');
if (file_exists($filename.".pdf")) unlink($filename.".pdf");
$pdfWriter->save($filename.".pdf");
but when I try to load the file to convert it to PDF I get the following exception while loading the file
Fatal error: Uncaught exception 'BadMethodCallException' with message 'Cannot add PreserveText in Section.'
After some research I found that some others also have this bug (phpWord - Cannot add PreserveText in Section)
EDIT
After trying around some more I found out, that the Exception only occurs when I have some mail merge fields in my document. Once I removed them the Exception does not come up anymore, but the converted PDF files look horrible. All style information are gone and I can't use the result, so the need for an alternative stays.
I thought about using another way to generate the PDF, but I could only find 4 ways:
Using OpenOffice - Impossible as I cannot install any software on the Server. Also going the way mentioned here did not work either as my hoster (Strato) uses SunOS as the OS and this needs Linux
Using phpdocx - I do not have any budget to pay for it and the demo cannot create PDF
Using PHPLiveDocx - This works, but has the limitation of 250 documents per day and 20 per hour and I have to convert arround 300 documents at once, maybe even multiple times a day
Using PHP-Digital-Format-Convert - The output looks better than with PHPWord and tcpdf, but still not usable as images are missing, and most (not all!) of the styles
Is there a 5th way to generate the PDF? Or is there any solution to make the generated PDF documents look nice?
I used Gears/pdf to convert the docx file generated by phpword to PDF:
$success = Gears\Pdf::convert(
'file_path/file_name.docx',
'file_path/file_name.pdf');
You're trying to unlink the PDF file before saving it, and you have also to unlink the DOCX document, not the PDF one.
Try this.
$pdfWriter = \PhpOffice\PhpWord\IOFactory::createWriter($wordPdf , 'PDF');
$pdfWriter->save($filename.".pdf");
unlink($wordPdf);
I don't think I'm correct..
You save the document as HTML content
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'HTML');
After than you read the HTML file content and write the content as PDF file with the help of mPDF or tcPdf or fpdf.
Try this:
// get the name of the input PDF
$inputFile = "C:\\PHP\\Test1.docx";
// get the name of the output MS-WORD file
$outputFile = "C:\\PHP\\Test1.pdf";
try
{
$oLoader = new COM("easyPDF.Loader.8");
$oPrinter = $oLoader->LoadObject("easyPDF.Printer.8");
$oPrintJob = $oPrinter->PrintJob;
$oPrintJob->PrintOut ($inputFile, $outputFile);
print "Success";
}
catch(com_exception $e)
{
Print "error code".$e->getcode(). "\n";
print $e->getMessage();
}
I have run into a problem with Apple's unfortunate decision to create a PNG file format that isn't actually a PNG file format. I pulled a PNG image file from an app IPA file and attempted to display it on a web browser and found that web browsers don't know how to display them and give an error. It took me some time to discover that the original, unzipped image was even the problem in the first place.
After researching the issue and doing a lot of poking around, I finally found this script as I don't have the knowledge to create a class to do what I need:
https://gist.github.com/juban/8397183
The author says this is a PHP scripted version that will turn an apple PNG file into a standard PNG file so that it can display properly. For added information, I am running PHP 5.5+.
My process of pulling out the image file goes like this:
if ($zip->open($ipaFile) === TRUE) {
if($zip->locateName($iconFilePath.$iconFile) !== FALSE) {
if ($iconData = $zip->getFromName($iconFilePath.$iconFile)) {
$iOSNormalizer = new iOSPNGNormalizer();
$iconData = $iOSNormalizer->getNormalizedPNG($iconData);
file_put_contents($iconSaveFile.$newIconFile, $iconData);
}
}
}
The iOSNormalizer is a class you can look at by clicking on the link I gave.
When I run it through the class I get hung up with the following errors:
Warning: zlib_decode(): data error in mypage.php on line 524
Notice: Uninitialized string offset: 12840 in mypage.php on line 532
Notice: Uninitialized string offset: 12840 in mypage.php on line 532
...These last two notices are repeated a ton of times for a lot of different lines. What happens is the apple PNG file has its original widths and heights restored, runs into the zlib_decode() error, and then stops working. The outputted file is a blank white image with its original height and width. zlib_decode() is not documented well for PHP and I'm not sure how to fix this problem. I'm hoping someone can look at the class in the link and better understand why this may be happening. Thanks!
EDIT: To ensure it isn't anything to do with how I am pulling out the icon file from the IPA file, I tested the following code on the image attached at at the end of my question and I still have the same problem (again, see the PHP class in my link to see what the function getNormalizedPNG() does):
$iconFile = "/path/AppIcon40x40#2x.png";
$newIconFile = "/path/converted.png";
$iOSNormalizer = new iOSPNGNormalizer();
$iconData = $iOSNormalizer->getNormalizedPNG($iconFile);
file_put_contents($newIconFile, $iconData);
Example PNG
I have a DB system built in PHP/MySql. I'm fairly new at this. The system allows the user to upload an invoice. Others give permission to pay the invoice. The accounting person uploads the check. After check is uploaded, it generates a PDF as a cover, then uses PDFTK (using Ben Squire's PDFTK-PHP-Library) to combine all of the files together and present the user with a single PDF to download.
Some users upload PDF files which cause PDFTK to hang indefinitely when it tries to combine the PDF with others (but most of the time it works fine). No returned error, just hangs. In order to get back onto the sytem, user must clear cache and re-log in. There are no error messages logged by the server, it just freezes. The only difference I can find in the files that do or do not work in looking at them with Acrobat is that the bad files are legal sized (8.5 x 14) ... but if I create my own legal sized file and try that, it works fine.
Using Putty I've gone to command line and replicated the same problem, PDFTK can't read the file, it hangs on the command line as well. I tried using PDFMerge which uses FPDF to combine the files and get an error with the file as well (The error I get back from this is: FPDF error: Unable to find object (4, 0) at expected location). On the command line I was able to use ImageMagick to convert PDF to JPG, but it gives me an error: "Warning: File has an invalid xref entry: 2. Rebuilding xref table." and then it converts it to a jpg but gives a few other less helpful warnings.
If I could get PHP to check the PDF file to determine if is valid without hanging the system, I could use ImageMagick to convert the file and then convert it back to a PDF, but I don't want to do this to all files. How can I get it to check the validity of the file when uploaded to see if it needs to be converted without causing the system to hang?
Here is a link to a file that is causing problems: http://www.cssc-testing.org/accounting/school_9/20130604-a1atransportation-1.pdf
Thanks in advance for any guidance you can offer!
My Code (which I'm guessing is not very clean, as I'm new):
$pdftk = new pdftk();
if($create_cover) { $pdftk->setInputFile(array("filename" => $cover_page['server'])); }
// Load a list of attachments
$sql = "SELECT * FROM actg_attachments WHERE trans_id = {$trans_id}";
$attachments = Attachment::find_by_sql($sql);
foreach($attachments as $attachment) {
// Check if the file exists from the attachments
$attachment->set_variables();
$file = $attachment->abs_path . DS . $attachment->filename;
if(file_exists($file)){
// Use the pdftk tool to attach the documents to this PDF
$pdftk->setInputFile(array("filename" => $file));
}
}
$pdftk->setOutputFile($save_file);
$pdftk->_renderPdf();
the $pdftk class it is calling is from: https://github.com/bensquire/php-pdtfk-toolkit
You could possibly use Ghostscript using exec() to check the file.
The non-accepted answer here may help:
How can you find a problem with a programmatically generated PDF?
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.