note 13484 deleted from function.header by jimw

From: 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 :)

« previous php.notes (#19790) next »