I am using mpdf to generate the pdf files using PHP. I am successfully able to output the pdf as inline browser as well as force download using the mpdf options.
My question is do we need to send any HTTP Header information? or mpdf handles that part automatically? I am asking this because some browser may require some kind of header information to make pdf files work properly.
Please note that we are asking about the headers related to PDF file only.
E.g.
header("Content-type: application/pdf");
header("Content-Description: PHP Generated Data");
header("Content-Transfer-Encoding: binary");
header('Content-Length:' . filesize($file));
Thanks
mPDF handles the appropriate headers automatically when using the DESTINATION::INLINE or DESTINATION::DOWNLOAD options. You can see the exact headers that are set in the code.
Feel free to set additional custom headers if you need to, however it's not needed to correctly view / download the generated PDF document.
Related
On a webservice I'm developing, a user should be able to download his data in a HTML file. This file contains everything (including images as base64).
Now to make the user download this, I would have to create the file and save it on my webserver. Afterwards, I'd have to delete it using a cronjob, because I can't figure out when the download is complete.
Is there another way? Would it be possible to download a file to the user which does not physically exist on my webserver, but gets somehow created temporarily?
Thank you for your help!
As far as the WWW is concerned, there is no such thing as a file. There are just HTTP resources.
The server might get the data from a file, it might not.
Just output the data for the file from your PHP program. (i.e. by putting it outside <?php and ?> or using echo or any other technique that causes PHP to output something).
You need to make sure you use the right Content-Type header, but since you are using HTML, that is text/html which is the default.
You can add a Content-Disposition header if you want the user to be prompted to save their download somewhere instead of rendering the downloaded HTML in the browser window.
header("Content-Disposition: attachment; filename='foo.html'");
<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// The PDF source is in original.pdf
readfile('original.pdf');
?>
From: http://php.net/manual/en/function.header.php
I'm trying to make a simple script that does two things:
Serves up a file and hide's it's destination
Has a download counter
Now, I'm doing this in the wordpress environment, but this question isn't completely wordpress-related so I figured I would ask here.
Basically, the way I have it set up, currently, is I have a link that when you click it sets a $_['GET'] which is then checked if is set. If it is set, the download file is served.
the link: Click here!'
the $_['GET'] code: http://pastebin.com/93nD43gA
There is a bit of wordpress jargon in the code, but basically it's checking a download count user_meta and if it's > 0, serveFile() is called.
The main problem I'm having here is, if I click the link, readfile() loads the actual file contents INTO the window (garbled text). If I add a target=_blank to the <a> it opens a new browser window and loads the contents INTO the window.
This approach seemed to work perfectly fine when I was doing it as stand-alone php files. My main issue is that I need to keep the wordpress space so I can call functions, etc. associated with it.
I have tried using the $_['GET'] on both the self page, another page with a custom template (the code in the pastebin above), and as a stand-alone php file. Both the first two options load the file INTO the window. The third doesn't preserve wordpress functions, even if I include blog-header.php.
Can anyone point me in to the right direction of how to get the file to force download and not load INTO the window?
You need to set the appropriate header for whatever the file type is. For example, if readfile always serves, PDFs, it should be done like this:
// disable browser caching -- the server may be doing this on its own
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Type: application/pdf');
//forces a download
header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=filename.pdf');
readfile($file);
Keep in mind that header only works if you have not sent any data in the request at all including whitespace.
The 'garbled' text is what you want however besides that you have to set a mime. This can be accomplished by simply setting a header, e.g. header("Content-Type: image/png");
If the file mimes will vary (e.g. pdf, doc, png, etc) you should look into finfo extension. With it you can get the full and correct mime of the file
<?php
$finfo = new \finfo(FILEINFO_MIME);
$mime = $finfo->file('path/to/file', FILEINFO_MIME_TYPE);
header("Content-Type: $mime");
As noted - headers can be set only if no write to output has been done (no echo's, print, etc. Output buffering could help you here).
I want to read the pdf documents and display the content to the browser, without allowing the users to save a copy of the pdf.
How can i use fpdf for this purpose? So far, i could not figure out a way of reading a pdf document with fpdf, apart from creating a new pdf. Can anyone suggest an example of reading a pdf file, and if possible, how to disable the save as pdf option?
fpdf can't read pdf's. take a look at it's FAQ - 16 an 17 sound interesting and it loooks like there are addons to do this.
what you really can't ever avoid is to let the user save that pdf - it has to be sent to the browser at the clients machine, to display it, so there will always be a possibility to save it. a possibility would be to transform every page of the pdf to an image (using Imagemagick for example) and oly display these images, so the user can't copy the text from it and has no possibility to get the original pdf-document - but that will only annoy people.
If you have an existing PDF you want to display it inline rather than ask them to download it:
// Path to PDF file
$file = "blah.pdf";
// Show in browser
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit();
You don't need to use FPDF that's only a class that helps you create PDF's from scratch.
Also bare in mind there is nothing to stop a user from saving a PDF even when displaying inline.
Im not sure if this is possible, check the FPDI extension for FPDF here: http://www.setasign.de/products/pdf-php-solutions/fpdi/
To convert a pdf to html there a program for linux called pdftohtml. However be aware that the result of this will not create something that looks like the original pdf and in many cases (locked pdf's etc) it will fail. What is a possible solution is generating an image of each page using a program like ImageMagick, then place the html over on an invisible layer to allow for interaction. I'd still rather go for displaying the pdf inline if I were you though.
I have a script where I get the contents of a file and then echo it to the screen, the problem is that it actually echos the binary file to the page, what I want if for it to act like a download where the download dialog will display.
how can I achieve this?
From the PHP header() manual:
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// The PDF source is in original.pdf
readfile('original.pdf');
Change the content-type and the filename. You can user readfile over file_get_contents, but either or should work.
You use the unofficial but ubiquitously supported Content-disposition header. See the first example here. There are a few quirks in browser support for the filename.
You could also simply change the Content-type header to application/octet-stream, but then you can't suggesta a filename to the user without more complex mechanisms.
(Note: application/binary is perhaps an option that's better than application/octet-stream because "If Content-Type matches one of generic values, such as application/octet-stream [...], many browsers treat this as a permission to second-guess the value based on the aforementioned signals, and try to come up with something more specific. The rationale for this step is that some badly configured web servers fall back to these types on all returned content." Source: Google Browser Security Handbook).
You have to change the Content-Type of the HTTP response.
In "raw" PHP (ie. without use of any framework), it would look like:
header("Content-Type: application/octet-stream");
It is necessary to invoke it at the beginning of the script, before any of the data is echoed.
Thanks #Brad for the answer. i have done some modifications in it. What i found is if my content is echoed than no need to do "readfile". What i have done is.
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="download.pdf"');
$pdf = $thirdPartyAPI->getPdf($ID);
echo $pdf;
ob_clean();
flush();
exit;
I have a script that generates data in csv format which is sent to the user along with a set of headers that tell the browser it is a .csv file. Everything works great when users (left)click on the link to the script, they are presented with a download dialog with the filename ending in .csv and it suggests using excel, or calc, to open it. However, when users right-click and choose Save As it is being saved with the php script name.
Here is the header code:
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
$val = date("m_d_Y_g_i");
Header('Content-Disposition: attachment; filename="personal_information_'.$val.'.csv"');
So again, when users left-click it saves the file as personal_information_date.csv; when they right click it saves as download.php. I'm using FF3. Oddly enough, IE7 does not have this problem.
Any ideas?
Use mod_rewrite to alias the file from file.csv to file.php, this is a browser issue rather than PHP because by saving the file it isn't running it before it is saving it.
So to summarise:
Link to personal_information_date.csv
Create a mod_rewrite rule that forwards personal_information_date.csv to download.php (e.g.: RewriteRule ^personal_information_date.csv$ download.php).
The HTTP client may ignore more than one content type header, the two other will be ignored - which of them? Depends on the browser implementation, therefor the different behaviour. The correct mime type is text/csv, not application/octet-stream! The content-disposition header is correct for the download.
I believe that setting three different mimetypes doesn't help
what's $val ? Is this known content or user provided - e.g. could it contain nasty characters (like ") or even linebreaks, e.g. introduce new HTTP header lines?
have a look at the HTTP-Headers that arrive at the client. Either the Firefox built-in information or use LiveHttpHeaders (plugin to be found at the Mozilla site - logs all HTTP-Headers) - I'm sure there are more/other plugins for FF available.
Hope this helps.