note 13484 deleted from function.header by jimw
| From: | jimw@php.net | Date: | Wed, 31 Oct 2001 22:04:55 +0000 |
| Subject: | note 13484 deleted from function.header by jimw | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-19790@lists.php.net to get a copy of this message | ||
Again on the problem of letting users download files from your local disk (which however are NOT
under the document root of the web server, so they cannot download them directly). I am using (after
lots of trial & error) a function that looks like this:
function download($file, $type = false, $name = false, $down = false) {
if(!file_exists($file)) exit;
if(!$name) $name = basename($file);
if($down) $type = "application/force-download";
else if(!$type) $type = "application/download";
$disp = $down ? "attachment" : "inline";
header("Content-disposition: ".$disp."; filename=".$name);
header("Content-length: ".filesize($file));
header("Content-type: ".$type);
header("Connection: close");
header("Expires: 0");
set_time_limit(0);
readfile($file);
exit;
}
Here $file is the absolute path of the file (on the local filesystem), $type is its MIME type (such
as "application/pdf") and $name is the optional filename (such as "a.pdf") used
for downloading. $down controls the download behaviour; if true a "Save as" dialog is
forced, otherwise the file is displayed inside the browser (if this is possible, depending on file
type).
This works perfecly in Netscape 4.77 and Mozilla/5.0 (0.9.1+) (in Win2K). In Internet Explorer
(5.01), however, it only works for types like "text/plain", "text/html" and
"image/jpeg" but NOT for types like "application/pdf",
"application/msword" and "application/x-zip-compressed". In the later case the
browser responds "Internet Explorer was not able to open this Internet site. The requested site
is either unavailable or cannot be found." and of course, nothing is downloaded. The weird
thing now: if the same URL is accessed through an <A HREF>, it works just fine, as said in the
previous note :)
After trying for 2 days, I found that the problem is not in the above function, but in my use of
sessions (I use session variables for providing authentication & access control). Before coming
to download(), I usually do something like:
session_start();
session_register("user", "admin");
I noticed that when session.cache_limiter is set to "nocache" in php.ini (which is the
case by default), this automatically introduces the following headers:
Expires: 0
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Now if you do session_cache_limiter("") BEFORE session_start() everything works perfectly!
Of course, the browser is now free to cache the file, which might not be exactly what you want. It
is possible though to manually add all of the above headers, EXCEPT "no-store" &
"no-cache" in cache-control, which cause the problem.
One more thing on the filename: in most cases the one provided in the
"content-disposition" header is ignored, and the script's name is actually used (like
"download.php" $@%!^@). An easy trick is to add the name in the URL: instead of "http://your.host/your/dir/download.php?your=params"
just use "http://your.host/your/dir/download.php/a.pdf?your=params"
and the file is seen as "a.pdf"!
I hope this was useful :)