How to embed dynamic PDFs? - php

I have a website that dynamically generates PDFs using FPDF (from fpdf.org) based on an HTML form passed to a PHP script. As of right now, it all works fine to the point where the information passes through and the FPDF generates the PDF. However, I've been looking into embedding options and can't quite get it to work properly. I have other areas of my page that embed PDFs, but they are ones that I generate and save to the server. My question is, is it possible to dynamically generate a PDF and output it directly to the browser ($pdf->Output();) inside an emedded area of an HTML page? Right now it just generates and takes up the entire window, but I would like to include other information along with the PDF, such as instructions and what not. I attempted to output the pdf as a string into a variable, via:
$output = $pdf->Output('','S');
This did output the information as a string into the $output variable; however, I wasn't sure if I was able to embed that. I tried specifying a MIME type (as application/pdf), but the only other available attribute is src, so I wasn't sure if I could use the string anywhere. I have used 2 different techniques for embedding PDFs in the past. tags and an with google document viewer, but after toying with them for a while, I wasn't able to get this to work =( Anyone have any ideas?

When you save fpdf as a string, you can use php to encode it to base64 and then pass that to whatever you are using to embed your pdf in your html document.
PHP:
$output = $pdf->Output('','S');
$output = base64_encode($output);
In your html document:
<embed src="data:application/pdf;base64,<?php echo $output ?>" type='application/pdf'>
I know this will work in at least chrome. I have not tested it in other browsers. You may need to implement other way to embed pdf's into html pages in order to achieve cross-browser support. I assume that you can figure this out from this point. Hope this helps somebody.

the PDF embedded is based on the browser capabilities.
You can use frames and show the instructions on the upper or left side of the page and the pdf on the rest.
and as you said you can use Google docs, but it transforms the whole document into images for embedding.

If you are using the same FPDF I am, then you already have all you need!
Simply change your 'I' into 'D' to force downloading, rather than inline.
from:
function Output($name='', $dest='')
{
//Output PDF to some destination
if($this->state<3)
$this->Close();
$dest=strtoupper($dest);
if($dest=='')
{
if($name=='')
{
$name='doc.pdf';
$dest='I';
}
else
$dest='F';
}
switch($dest)
{
case 'I':
//Send to standard output
if(ob_get_length())
$this->Error('Some data has already been output. Can\'t send PDF file');
if(php_sapi_name()!='cli')
{
//We send to a browser
header('Content-Type: application/pdf');
if(headers_sent())
$this->Error('Some data has already been output. Can\'t send PDF file');
header('Content-Length: '.strlen($this->buffer));
header('Content-Disposition: inline; filename="'.$name.'"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
ini_set('zlib.output_compression','0');
}
echo $this->buffer;
break;
case 'D':
//Download file
if(ob_get_length())
$this->Error('Some data has already been output. Can\'t send PDF file');
header('Content-Type: application/x-download');
if(headers_sent())
$this->Error('Some data has already been output. Can\'t send PDF file');
header('Content-Length: '.strlen($this->buffer));
header('Content-Disposition: attachment; filename="'.$name.'"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
ini_set('zlib.output_compression','0');
echo $this->buffer;
break;
case 'F':
//Save to local file
$f=fopen($name,'wb');
if(!$f)
$this->Error('Unable to create output file: '.$name);
fwrite($f,$this->buffer,strlen($this->buffer));
fclose($f);
break;
case 'S':
//Return as a string
return $this->buffer;
default:
$this->Error('Incorrect output destination: '.$dest);
}
return '';
}

Related

Open PDF from FPDF in new tab

I have a process where customer clicks if he wants a report to be generated and downloaded while creating a business unit. This report will be in pdf format.
Currently I am using Codeigniter and I use FPDF to generate pdf files.
The pdf opens well when it is requested. But
Problem:
1) PDF opens in the same tab. I would like the pdf to open up in new tab which I am kind of thinking how.
"_target" will help me open the pdf in new tab if it is a pdf link. But here it is server side generated pdf. Hence "_target" will not work so I am looking for alternative on this.
2) After the pdf generates, the next line of code is not read. The execution actually stops here. I would like to know how I can make the process continue even after outputting pdf file.
Example
$pdf->Output($exampleArray, 'D'); // exampleArray carries all data to PDF and helps output the pdf and D forces FPDF to download PDF rather than opening it. Instead of 'D' I can use 'I' but that will output the pdf in same tab.
$this->continueNextFunction(); // This function should run and open the views in it.
From the above example I would love to see either PDF downloaded or 'opened in new tab' followed by next line executed helping the page to redirect and open required views.
Also please let me know if further explanation is required. I tried my best to explain the situation here. I had looked on this over google but I have not really found any solution on this.
Any help regarding this will be greatly appreciated.
You should create the new tab before running the FPDF code.
Alternative you can save the pdf as a file and open a new tab with the correct header.
see this question: Show a PDF files in users browser via PHP/Perl
The code terminates with output by design, unless you save it to file or string.
$pdf->Output($filename,'F');
If you could elaborate on what you want to do after the output i might be able to help more.
Here is what we are doing and some thoughts:
The Output() method takes 2 arguments, name and dest. You are sending an array in for the name parameter, probably not what you want. The second, dest, will use the "D" as you have specified.
Output() sends headers and the data depending on the value you specify for dest. See below.
What that means is if you want to continue executing code, you are likely going to need to separate out the logic that generates this PDF into a new page, open that in the new tab using target="_new" like you were thinking, which then prompts the user to download or in that case you can use the "I" value and open it within the browser.
Output() from fpdf.php [lines 999-1036]:
switch($dest)
{
case 'I':
// Send to standard output
$this->_checkoutput();
if(PHP_SAPI!='cli')
{
// We send to a browser
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="'.$name.'"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
}
echo $this->buffer;
break;
case 'D':
// Download file
$this->_checkoutput();
header('Content-Type: application/x-download');
header('Content-Disposition: attachment; filename="'.$name.'"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
echo $this->buffer;
break;
case 'F':
// Save to local file
$f = fopen($name,'wb');
if(!$f)
$this->Error('Unable to create output file: '.$name);
fwrite($f,$this->buffer,strlen($this->buffer));
fclose($f);
break;
case 'S':
// Return as a string
return $this->buffer;
default:
$this->Error('Incorrect output destination: '.$dest);
}

Is correct to send HTML and a PDF file in the same request?

I have to send a PDF to the user, but this PDF is generated by a command line tool executed from PHP (server side). When the user clicks on a link this is executed:
window.open($(this).attr('href'), "mywindow",
"height=600,width=600,menubar=0,location=0,status=0,toolbar=0");
The new window is generated from PHP:
<?php
ob_start();
?>
Web page contents to be printed
<?php
$content = ob_get_contents();
ob_end_flush();
$input = "/tmp/input.html";
$output = "/tmp/output.pdf";
file_put_contents($input, $content);
create_pdf($input, $output);
$state = filesize($output);
if ($state !== FALSE && $state != 0) {
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename=file.pdf');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($output));
ob_clean();
flush();
#readfile($output);
}
unlink($input);
unlink($output);
Why this? Because if there is a problem generating the PDF file it will not be sent, but the equivalent HTML file will be rendered (if stament) and if there is a problem sending the PDF (it occurs sometimes) the user will have a printable HTML alternative.
I've tested this on chrome and it works perfect (shows the inline PDF when it has been generated or shows the equivalent webpage when it's not generated). The Firefox I have doesn't support inline PDF (no plugin) so it just ask the user to download the PDF and closes the window (expected result).
My doubt is if this way to generate an alternative to PDF is valid or it could be "banned" in future versions?
You can send any content you like from any URL provided that the headers returned to the client are appropriate for the content.

Dynamic creation of a doc/docx document on the users desktop

My site is HTML/Javascript with AJAX calling server-side PHP. I want to allow the user to click an icon and create a report from MySQL data and then save this on the client's desktop without doing a page reload.
Options for creating a doc, as I can gather it, appear to be as follows. (I gather it needs to be done server-side, rather than with Javascript.) I'm not sure where the file ends up in each case. Please feel free to correct my misunderstandings :)
Method 1 - this appears only to create a .doc file. I'm not sure where the file gets put.
$fp = fopen("method1.doc", 'w+');
$str = "<B>This is the text for the word file created through php programming</B>";
fwrite($fp, $str);
fclose($fp);
Method 2 - this also appears to create a .doc file.
$word = new COM("word.application") or die ("couldnt create an instance of word");
echo "loaded , word version{$word->version}";
$word->visible = 1;
$word->Documents->Add();
$word->Selection->TypeText("Sample text.");
$word->Documents[1]->SaveAs("method2.doc");
$word->Quit();
$word->Release();
$word = null;
Method 3 - also a .doc file, I think.
header('Content-type: application/vnd.ms-word');
header("Content-Disposition: attachment;Filename=method3.doc");
echo "<html>";
echo "<body>";
echo "<b>My first document</b>";
echo "</body>";
echo "</html>";
Method 4 - PHPWord
Method 5 - PHPDocx
I've tested 1 & 2 in my home dev environment, but I can't find the files! What's the best way forward, please?
Thanks :)
BTW, I know there are relevant posts here, here and here, but none really answers the question.
If you want to have an icon, and when the icon is clicked it makes a download without page reload, then you just have to make a link to the icon that bring to a script that start a download using the appropriate headers.
Example :
header ('Pragma: no-cache');
header('Content-Disposition: attachment; filename="'.$File.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$Len);
Doing this, the download will start, but the page where the user has clicked will not be changed, neither reloaded.
If you want to generate dynamic DOCX files to be downloaded, I recommend to use OpenTBS. This library can generate a DOCX (and XLSX, PPTX, ODT, ODS, ...) using templates. It has a function that let you send the result directly as a download, without temporary files, or let you save is in the server side.
Methods 1 & 2 create document on the server side somewhere in filesystem (after that you need to transfer it to the client).
Method 3 creates document as a response to client request - depending on settings browser will either save it or open in window (or ask 'Save/Open/Cancel?').
I personally would have made java applet or flash application which will have access to your local filesystem. It can load document from server and save to local file system without page reloads.

Show a PDF files in users browser via PHP/Perl

I want to show my users PDF files. The reason why I use CGI to show the PDF is I want to track the clicks for the PDF, and cloak the real location of the saved PDF.
I've been searching on the Internet and only found how to show save dialog to the users and creating a PDF, not show the files to the users.
What I wanted for is show the users my PDF files, not creating or download the PDF.
Here is what I got form the official PHP documentation:
<?php
header('Content-type: application/pdf');
readfile('the.pdf');
?>
Also my google-search-result perl code:
open(PDF, "the.pdf") or die "could not open PDF [$!]";
binmode PDF;
my $output = do { local $/; <PDF> };
close (PDF);
print "Content-Type: application/pdf\n";
print "Content-Length: " .length($output) . "\n\n";
print $output
if you do it on ruby, please say it to me. But I'm not sure if my server support rails.
Sorry if my code is too far away from the method to show the pdf, since I don't know anything about pdf processing and how to implement this problem.
Lets assume that the users have the Adobe Reader plug-in. So, how to fix my problem?
edit : I want to show plain PDF file. My primary purpose: track my pdf files and use some fancy urls.
edit : Here's my main php code:
<?php
$file='/files/the.pdf';
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="the.pdf"');
#readfile($file);
?>
edit : Now the code is working. But the loading progress bar (on Adobe Reader X plugin) doesn't shows up. Why? Anyone can help me? Here's my main code:
<?php
$file='./files/the.pdf';
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="the.pdf"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));
#readfile($file);
?>
edit : All my problems solved. Here's the final code:
<?php
$file = './path/to/the.pdf';
$filename = 'Custom file name for the.pdf'; /* Note: Always use .pdf at the end. */
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));
header('Accept-Ranges: bytes');
#readfile($file);
?>
Thanks! :)
I assume you want the PDF to display in the browser, rather than forcing a download. If that is the case, try setting the Content-Disposition header with a value of inline.
Also remember that this will also be affected by browser settings - some browsers may be configured to always download PDF files or open them in a different application (e.g. Adobe Reader)
$url ="https://yourFile.pdf";
$content = file_get_contents($url);
header('Content-Type: application/pdf');
header('Content-Length: ' . strlen($content));
header('Content-Disposition: inline; filename="YourFileName.pdf"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
ini_set('zlib.output_compression','0');
die($content);
Tested and works fine. If you want the file to download instead, replace
Content-Disposition: inline
with
Content-Disposition: attachment
You could modify a PDF renderer such as xpdf or evince to render into a graphics image on your server, and then deliver the image to the user. This is how Google's quick view of PDF files works, they render it locally, then deliver images to the user. No downloaded PDF file, and the source is pretty well obscured. :)
The safest way to have a PDF display instead of download seems to be embedding it using an object or iframe element. There are also 3rd party solutions like Google's PDF viewer.
See Best Way to Embed PDF in HTML for an overview.
There's also DoPDF, a Java based In-browser PDF viewer. I can't speak to its quality but it looks interesting.
You can also use fpdf class available at: http://www.fpdf.org.
It gives options for both outputting to a file and displaying on browser.
There is a simple solution using the embed tag:
<span class="fileShow">
<a href="aa.pdf" onclick="event.stopPropagation();" target="_blank">
<embed style="width:450px; height:300px; max-width:450px; max-height:300px" src="aa.pdf">
</a>
</span>

FPDF ouput() saves file with html extension

I'm saving a PDF document with FPDF using the following code...
$pdf->Output('doc.pdf','D');
...but it saves it as 'doc.pdf.html'
Why is it adding the html extension?
The problem for this in my case, was that I was not terminating the script right after I echo'd out the PDF. I was using a framework and letting it finish out which was causing the problem. So just add an "exit" statement and it should fix it.
It does not add a '.html' extension:
source code:
case 'D':
//Download file
if(ob_get_length())
$this->Error('Some data has already been output, can\'t send PDF file');
header('Content-Type: application/x-download');
if(headers_sent())
$this->Error('Some data has already been output, can\'t send PDF file');
header('Content-Length: '.strlen($this->buffer));
header('Content-Disposition: attachment; filename="'.$name.'"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
ini_set('zlib.output_compression','0');
echo $this->buffer;
break;
so the problem must be somewhere else.

Categories