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
Related
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).
So I'm trying to both dynamically create a .doc file and have the user download it when he clicks a button.
These are the headers i found to download a file
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
And these are the headers i found to make a a word document
header('Content-type: application/vnd.ms-word');
header('Content-Disposition: attachment; Filename='.$myFile);
I'm just having a hard time just fitting the picture together because they both tasks have a 'Content-Type' header. Do i create the file first, save it, then download it? Or can i do it all (create a doc file and have user download it) in one php file?
You only need the "headers found to make a word document." The first set are for a generic streaming download.
Your second set of headers are fine. No need for the first. The Content-Disposition header is the one that will typically force a download. (Although, you should be aware that clients can do whatever they want with a file, and you have no direct control over this.)
You can create the file and send it straight to the client without saving it to the server's disk, depending on how you are creating this document.
Hi I want to have the option on my site for the user to download a CSV file. I have used the code below
<input type="button" value="Download as CSV file" window.location.href='call_log.csv' " />
This does work but when the button is clicked the file is opened in another tab on my browser, What I want to happen is a download straight to the users default download folder
I posted this question before and the response was to include headers ie
Content-Disposition: attachment; filename="call_log.csv"
The page is a php file and if I include headers the page does not load but trys to download the whole page .
Surely I cant put headers in the CSV file , can anyone help me please ?
Thanks
Your server needs to bet set to execute your php script - you're right; there's no need to change that.
What you need to do is send the correct header to the server from your php script. Here's an example from php.net:
<?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');
?>
For your csv file, the correct content type is text/csv
I have an XML feed generated by a PHP script with mod_rewrite running. IE opens the feed OK but I cannot get it to save the file to disk or import to Excel.
The file I am trying to access in the url is similar to:
http://domain.com/download/export.xml
This gets written to a download PHP script and is not actually an XML file.
After setting the headers as below, it is still not possible to get IE to save the file. Also, as it is not capable of displaying the plain source, copy & paste into notepad will not work because of various styling changes IE makes to the XML.
<?php
header("Content-type: text/xml");
header('Content-Disposition: attachment; filename="QuoteExport_'.$quoteDate.'_'.$quoteSlot.'.xml"');
Does anyone know the solution? Thanks.
Edit:
Thanks for the help so far. I have tried a combination of these headers and still not getting the results I want. No matter what I set, IE always displays it in-line in the browser with no option to download. The save functionality also still does not work either. Any other ideas how to force IE to save the XML as a file by using headers?
Edit2: The state now is that IE gives the option to open/save but whilst trying to save, there is a popup saying that it is "Unable to open this internet site.". Yet at the same time, the open option displays the content with no issues.
To force ie and other browsers to download you have to specify specific headers like in this example :
header("Content-disposition: attachment; filename=\"".$fileName . ".csv\"");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
header("Pragma: no-cache");
header("Expires: 0");
Other wise if you use text/xml, ie thinks he knows how to display it and does so.
You need to set a session parameter for some versions of IE. Assuming you have $my_file_name and $my_file_contents set, here's how it would look:
if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
session_cache_limiter("public");
}
session_start();
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename=".' $my_file_name '. "');
print($my_file_contents);
(Adapted from this article)
Try setting the content-type to application/xml or application/force-download
After spending much time changing the headers, I went for a slightly different approach. No matter what I was setting them to, it just would not work for me.
Anyway the solution implemented was:
When a client lands on the URL (http~://my-domain.com/downloads/export.xml), the PHP script generates a real XML file in the same location as the request-URI and saves it on the server, schedules it for a delete job in the future and then effectively refreshes the browser. Then, the mod-rewrite rules on the second request serve the actual file and then IE can use the file correctly. A future request then causes the cycle to run again.
Slightly round about way of doing things, but it was the fastest method. Also, I had the ability to schedule file operations from another part of the application making life much easier for clean-up!
Anyway thanks for the help and I did learn a thing-or-two about header options.
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;