I have a strange question regarding PDF.JS and PHP
Using PDF.JS, to open pdf you should use on browser:
http:// ...url... /viewer.html?file=[filename]
I have changed viewer.html extension to viewer.php and developed an additional file document.php to get data from database and load a local PDF file, and I use in this way to get PDF
... viewer.php?file=document.php&control=5E71581C52B96
All work great , AS ESPECTED, but i'm experiencing trouble when get variables from database.
When I Use fileurl like this, PDF load correctly:
$fileurl = 'D:\Drive\_DEV\storage\220\2020-03-17\00000000002\1584486427900.pdf';
When I use fileurl like this (variables from database) PDF not open and have error
Corrupted or inválid PDF Invalid PDF structure
$fileurl = $storage_path.'\\'.$storage_folder.'\\'.$document;
If I echo, $fileurl in both cases i have exactly same result.
Regarding SQL QUERY below, on WHERE Clause if I change '$doc_control' (from request) with '5E71581C52B96' (instead '$doc_control') PDF load correctly into pdf.js
If I echo $doc_control, number is exactly same, only difference is how put value on WHERE (number or variable)
If i open document.php work with no problems.
What do I Wrong? Any help is very appreciated.
DOCUMENT.PHP
// REQUEST
$doc_control = $_REQUEST['control'];
// Read database
SELECT *
FROM docs
WHERE doc_control = '$doc_control'
// FILE PATH
$fileurl = $storage_path.'\\'.$storage_folder.'\\'.$document;
// READ PDF
header("Content-type:application/pdf");
header("Content-Disposition:inline;filename=".$fileurl);
//#readfile($fileurl);
$file=fopen($fileurl, "r") or die('Unable to open file');
echo fread($file,filesize($fileurl));
fclose($file);
Related
Background
I am working on setting up an intranet webpage where the user can select an item from a list, and it will display information about that item and a PDF as a block element.
The PDFs will need to be updated and replaced by specific people, so they are stored on a separate file server on the internal network.
HTML Solution Attempt
I've tried using
<embed src="file:///myFileServer/PDFs/filename.pdf" width="1000" height="600" type="application/pdf">
but I get local resource errors:
Firefox: "Security Error: Content at myWebServer/file_read.php may not load or link to file:///myFileServer/PDFs/filename.pdf."
Edge/Chrome: "Not allowed to load local resource: file:///myFileServer/PDFs/filename.pdf"
I understand the error is because the PDF path is loaded by the browser, not the web server. This likely would be a problem even if it was allowed, because not all of the users would have access to the file server. Naturally, my next thought was to try using PHP to display the element so that the browser never needs to see a file path and the web server loads the PDF.
PHP Solution Attempt
I then tried using
<?php
$filename = "file:///myFileServer/PDFs/filename.pdf";
header("Content-type: application/pdf");
header("Content-Length: " . filesize($filename));
readfile($filename);
?>
This gave me the following warning, which had to do with the PHP that is used to load the page's navigation bar.
"Cannot modify header information - headers already sent by (output started at C:\Apache24\htdocs\nav.php:66) in C:\Apache24\htdocs\file_read.php on line 81"
Removing <?php include 'nav.php' ?> in the file_read.php caused the PHP code mentioned above to work, but not as I wanted. It basically loads a full-page PDF view as if you selected a PDF to open it in the browser, instead of displaying it as a page element.
PHP PDF to Base64 Solution
Since the above did not work, I kept digging for a solution. It's a little hacky, but I did find one solution that seems to works.
<?php
$fileLocation = "//myFileServer/PDFs/filename.pdf";
$pdf = chunk_split(base64_encode(file_get_contents($fileLocation))); //Convert to Base64
echo '<embed src="data:application/pdf;base64,' . $pdf . '" style="height:500px;width:80%;" title="test"></embed>';
?>
While this does work and the code is rather clean, it's a bit slow and I feel like there has to be a more efficient way to do this.
My Question
Is there a better way to deal with the limitations of loading a local resource from another internal server than converting the PDF to Base64?
I use the FPDF library to display online PDF files, with the ouput option « I » (which output the content to browser).
Then, I need to be able to save some of those generated pdfs on my server (like does the ouput option « F »).
In order to do that, I wrote this script:
$pdf_data = file_get_contents('https:/HOST/Folder/file.php');
$path =__DIR__.'/Folder/file.pdf';
file_put_contents( $path, $pdf_data );
It succeeds to create a file with pdf extension to the directory, but :
- I got an error: « Format error : not a pdf or corrupted » when I try to open the "pdf" file,
- The saved file is empty (?).
So, what is wrong?
How can I get the content generated by the php file, and save it as a pdf on my server?
Finaly, I forgot this script and found a new solution that works!
I set up two outputs into my PHP code build with FPDF, one to display the file online and one to save the file on the server.
The content generated by the PHP code is always displayed, and I control the PDF backup with a string on the first output.
So, when I need to backup, I use a Jquery function to execute the PHP code in the background and upload the PDF file (hidden iframe works too).
Below the end of my PHP code:
<?php
...
if (mycondition) {$string='F';}
else {$string ='I';}
...
$pdf->Output(__DIR__.'/../../Folder/file.pdf',$string); // save on the server
$pdf->Output('file.pdf','I'); // display on the browser
?>
Below the jQuery function I use:
<script type="text/javascript" src="./js/jquery.js"></script>
<script type="text/javascript">
var phpfile = <?php echo json_encode($Filename); ?>; // the php file to upload
function uploadpdf() {
$.get(phpfile);
return false; }
</script>
Hope this will help!
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();
}
In my webapp, I can generate pdf file from multiple odt files using gedooo on demand when the user go to this url: http://{base_url}/models/generer/{doc_id}, the modelsController generate the pdf and launch the download on the navigator.
Now I have to send to a distant application by webservice the content of pdf (like an attachment in email) from a model. The problem is to execute the pdf generation and integrate it in my request without store it on the server as file. I tried to do something like:
$pdf = new File('http://{base_url}/models/generer/{doc_id}');
$content = $pdf->read();
And I get an error. I am out of ideas, I need your help.
You can not transmit PDF (binary file).
if you want to transmit it in webservice, you have to convert it to base64
$file = file_get_contents('http://{base_url}/models/generer/{doc_id}');
$filedata = base64_encode($file);
now you can send this data in webservice
echo json_encode(array('file'=>$filedata));
I found the solution!
$this->requestAction($url);
that write the file in the folder of my webapp and
$content = file_get_contents($local_url)
I'm trying to debug this issue by posting raw PNG image data to the server with the help of Postman. Here's a screenshot, which might help to understand the issue:
On the server I'm receiving the file as follows:
$png = $GLOBALS["HTTP_RAW_POST_DATA"];
Then I write the data to a new file:
$fh = fopen($myFile, 'w') or die("can't open file");
fwrite($fh, $png);
fclose($fh);
The file gets saved correctly, but it now has a different file size,
417KB instead of 279KB which is the size of the original file.
Now of course, I can't do any image operation as none of the functions (such as getimagesize which returns bool(false)) recognizes the file as a valid image.
I have debugged this process to a point where the issue must be somewhere in the file operations, but I don't understand why the file just doesn't result in the very same file type and size as the original, when the only thing I am doing is using the same raw data.
UPDATE:
I've now compared the encodings of the original file with the uploaded one,
and the former is in ISO-8859-1 and it displays correctly, the latter is in UTF-8 and has about 138kB more in file size.
Now I've achieved to convert the file on the server to ISO-8859-1.
fwrite($fh, iconv("UTF-8", "ISO-8859-1", $png));
The resulting file does now have the same output file size (279kB),
but it is still not recognized as a PNG image, some information seems to still get lost.
UPDATE (1):
I've been able to examine the issue further and found out, that the original file is exactly 4 bytes bigger than the generated file, thus the resulting PNG seems to be corrupted.
UPDATE (2):
I'm now able to save the file and open it as a valid PNG. The following code seems to be saving the image correctly:
$input = fopen("php://input","r+");
$destination = fopen($myFile, 'w+');
stream_copy_to_stream($input, $destination);
fclose($input);
fclose($destination);
However when trying to open the file with the imagecreatefrompng function I get a 500 error. I'm now trying to figure out if it's a memory issue in PHP.
Problem might be the way you test your POST by copying the "binary" data into a text field.
If you paste the same data into a text editor you won't get a valid image file either when saving this with the png extension.
Try to build a simple form with file field to test your upload
I use nginx for uploads and haven't had a problem, but I use the standard PHP way of uploading files as per: http://www.php.net/manual/en/features.file-upload.post-method.php
I would suggest trying that.
Try using: < ?php $postdata = file_get_contents("php://input"); ?>
To get the raw data. I use it some times to get data sent from a ajax post on cake.