I redirect the visitors in my website from page A to page B. In page B I expect users to get the downloaded PDF file (to be downloaded when page B is loading).
I have taken the code from another article (see a previous question answered here) and my code of page B is the following:
<?php
header('Content-Disposition: attachment; filename=nature.pdf');
header('Content-type: application/pdf');
$fn=fopen("/wp-content/nature.pdf","r");
fpassthru($fn);
?>
The output is not by opening a download dialog box, instead some unreadable characters are displayed in browser such as the following (I have just picked up a small sample below):
%PDF-1.4 %���� 3 0 obj <>stream x���MK1�o�+�$zIg&�� V=T�=Xo����K��i+#V�yx3��(BX�pW`
Server: OS Linux; PHP version: 5.2.17
The visitor -> Browser: Firefox; OS: Windows 2000
Is it possible to fail due to the old OS on client side? If not, does anybody know a solution how to force the download? Any help would be highly appreciated.
Thanks.
Try it with the Content-Length header:
ob_clean(); ob_start();
header('Content-Disposition: attachment; filename=nature.pdf');
header('Content-type: application/pdf');
header ("Content-Length: ".filesize("/wp-content/nature.pdf"));
readfile("/wp-content/nature.pdf");
exit;
There was a quirk in the really old browsers when Content-disposition was first being introduced, some of the really old browsers wouldn't show the "Save As" dialogue unless it couldn't recognize the type of file you were trying to open. Try setting the Content-type to nothing (or something unrecognizable), and see if that'll force the older browser to pop the save-as dialogue.
header('Content-type: ');
If that works, then I'd suggest adding in a line of PHP to detect whether or not they're on an old browser before running that line, as modern browsers will use that header to determine what program the file should be opened with.
Related
I'm randomly getting download errors from a link on a page. I also simplified the link to a directory for easy usage in emails for users.
On the main page the link looks like this:
a href="http://myPage.com/Mac" target="_blank" id="macDownloadButton" class="downloadbutton w-button">Download Mac version</a>
On my server, that's a directory with an index.php in it which looks like this:
<?php
// mac version
$file="http://www.myPage.com/downloads/myApp_Mac.zip";
$filename="myApp_Mac.zip";
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
header('Content-Length: ' . filesize($file));
header('Content-Encoding: none');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=' . $filename);
readfile($file);
exit;
?>
Again, the reason I do this is so it's a simple link to send to users in email like, "http://myPage.com/Mac" and "http://myPage.com/Windows".
The weird thing is that it mostly works...but sometimes it doesn't.
What am I doing wrong?
It's hard to know precisely what's wrong unless you check for errors on your readfile() call.
But you're invoking your web server from your web server here when you specify a filename starting with http. You're doing
readfile('http://www.myPage.com/downloads/myApp_Mac.zip');
where you could just as easily do
readfile('../downloads/myApp_Mac.zip');
and read the zip file from the local file system to send to your user.
What's more, filesize('../downloads/myApp_Mac.zip'); will yield a numerical value quickly and send it in the Content-Length header. That will allow the browser, by knowing the total size of the file you're sending, to display a meaningful progress bar.
You should remove the Accept-Ranges header; the php program you showed us doesn't honor range requests. If you lie to the browser by telling it you do honor those requests, the browser may get confused and corrupt the downloaded copy of your file. That will baffle your user.
Your Content-Disposition header is perfect. It defines the filename to be used on your user's machine in the downloads folder.
Simple operations are more reliable, and this may help you.
The reason you got stat failed with link as an error message is this: stat(2) is a operating-system call that operates on files in local and mounted file systems.
As previously mentioned by O. Jones you should definitely always use your local file path.
Most of my previous issues have been mostly browser related where I needed to tweak/add a http header, and in one case I needed to send all the HTTP headers in lowercase but I haven't had an issue like that in years. My personal recommendation would be to use a solid download library/function - it will make a noticeable difference to your productivity as well as rule out most browser related issues you may come across.
I have used the codeIgniter download helper for the last 3 years and recommend it for 99% of use cases. At the very least I would recommend your read through it's code - you will probably find a few cases you have never even considered such as clearing the output buffer,mime detection and even a special case for Android 2.1 as well as a few headers you may or may not need.
If all else fails I have no idea what server your running this on but if you continue to have issues I would recommend monitoring which processes your machine is running while paying close attention to ram and IO usage. I've have encountered bad/misbehaving services that run periodically using 99% of my IO or ram for short intervals at a time that caused a few really odd and unexpected errors.
i have some file which generated dynamically and downloaded, code is running with no problem with other browser even on window 7 ie 10 working fine but not able two download file in window 8 ie10. i have also try to download simple text file with header text/plain which is also not downloading. it shows downloading prompt with the file name in which downloading code is there not the name i specified and nothing happen on clicking save in ie 10.working in other.
<?php
echo "this is sample text";
header('Content-type: text/plain');
//open/save dialog box
header('Content-Disposition: attachment;filename="sample.txt"');
?>
This was window 8 bug with IE 10 only that was fixed later :)
I did an xml file and force download it by these headers:
header('Content-disposition: attachment; filename="export.xml"');
header('Content-type: application/xml; charset=utf8');
readfile('export.xml');
But before the download I see a dialog that this file can be harmful for my computer? How to get rid of this dialog? Maybe my headers is wrong?
upd Well, can do nothing, I did a test on my test-hosting, u can check it here: site with generation link, and an xml file as is: export.xml
Try changing application/xml to text/xml. Probably your browser thinks that application means executable.
Try this :
<?php
header('Content-disposition: attachment; filename="export.xml"');
header('Content-type: "text/xml"; charset="utf8"');
readfile('export.xml');
?>
Note: This does not solve your issue, however it did solve an issue I had on my computer giving that notice (windows, chrome, apache webserver, PHP 5.4.10). I leave it here for future visitors.
Some browsers do not only look for the headers but also for the "filename" in the URL.
For example if you download a PHP file that contains XML, the browser might identify it as a dangerous file (because it can be executed on your system or is not within some whitelist or what not):
http://example.com/xml-download.php
A simple solution is to make this file not end with .php any longer, for example by adding a ?:
http://example.com/xml-download.php?
And continue with that to even signal the filename that way:
http://example.com/xml-download.php?export.xml
(the last one is not necessary but can be useful especially with some older browsers)
I am currently developing an application in PHP in which my server (a dedicated server) must to download a file, and the user should download the file in same time.
Here is an example :
Server start to download a file at a time A.
User wants to download this file at the time A + 3 seconds (for example)
I already solved the problem :"If the user downloads the file faster than the server..". But I didn't know how to make a php script in which the user is gonna to download the full file (it means that the size must be the full size of the file, not the size it's currently downloaded at the time A+3seconds). I already make that :
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$data['name'].'";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$data['size']);
readfile($remoteFile);
But it doesn't work, the user is gonna download just the size it is currently on the server (which corrupt the file) and not the full file...
If you have any solution, thank you.
You could probably pipe the file manually, by opening the connection and reading until you're past all headers. Then once you've figured out the Content-Length, send that to the user and just echo all remaining data you get (do use flush() and avoid output buffers).
Pseudocode(-ish):
open the file
# grab headers
while you didn't get all HTTP headers:
read more
look for the Content-Length header
send the Content-Length header
# grab the file
while the rest of the request isn't done
read more
send it to the user
flush the buffers
done
Expanding on #Tom answer, you can use cURL to greatly simplify the algorithm by using the CURLOPT_HEADERFUNCTION and CURLOPT_READFUNCTION callbacks - see curl_setopt().
Don't send the content-length header. It's not required assuming you're using http 1.1(your webserver almost certainly does). Drawback is their browser cant show download time/size remaining.
I have a file download function in my website. it works fine before. but after we moved the site to another server with runs PHP 5 (it runs on PHP 4 before). when click to download, it automatically adds a extra blank line at the beginning and the end of the file which we don't want to. Here is the code for downloading function:
header("Content-Type: application/gas");
header("Cache-control: private");
header("Content-Disposition: attachment; filename=aaa.gas");
Could anyone please help me out? Thanks!
There may be an extra blank line after the ?> that closes the PHP within the script. Exit the script after sending the file in order to prevent this from mattering.