Page 1 of 1
Question on using PHP for downloads
Posted: Sat Jan 17, 2004 10:16 am
by DuFF
I'm sure you've all seen them when you're downloading a file:
Code: Select all
Thank you for downloading the file!
If the download doesn't start within 5 seconds click here.
Now, I am currently making a site that lets users download files via PHP scripts, but mine works a little different. When the users click a link, it redirects them to download.php which increments the total downloads by 1 and then quickly redirects the user straight to the file (example: /path/to/file/file.zip). In fact you don't even see the download.php because it doesn't output anything to the browser, so all you see is the download popup straight away.
Now here's the question, is this a "bad" way of doing this? And if it is, what is happening on the other pages the make you wait 5 seconds to download?
Thanks in advance for any pointers.
Posted: Sat Jan 17, 2004 10:19 am
by Straterra
Code: Select all
<meta http-equiv="refresh" content="timeinseconds;url=your_url">
If you use the code above, instead of headers, you can get a time delay for the redirect.
Posted: Sat Jan 17, 2004 10:31 am
by Gen-ik
@ DuFF
I've personally been using the way you are suggesting for file downloads for a while now without any problems. User clicks on a link to something like download.php?file=fileToDownload and then download.php will spit out the relevant header information and file, and update and database info etc.
The only problem I have come across are the names of the file(s) which are downloaded. For example if I wanted download.php to kick out images.zip using the url download.php?file=images.zip then for some reason the name of the actual file is displayed as download.php?file=images.zip instead of just images.zip..... which is annoying for me and will probably cause some confusion for the user.
If anyone knows of a good work-around for getting the file names to display correctly then I think this method of file downloading is pretty solid, and (apart from the file names) I haven't had any trouble with it.
Posted: Sat Jan 17, 2004 11:05 am
by redmonkey
@
Gen-ik
try using content disposition....
Code: Select all
$file = 'readme.txt';
header("Content-Disposition: attachment; filename=" . '"' . $file . '"');
I have found that by enclosing the filename in double-quotes within the header definition, it seems to be recognised and handled by more browsers types.
Posted: Sat Jan 17, 2004 11:25 am
by Gen-ik
redmonkey wrote:@
Gen-ik
try using content disposition....
Code: Select all
$file = 'readme.txt';
header("Content-Disposition: attachment; filename=" . '"' . $file . '"');
I have found that by enclosing the filename in double-quotes within the header definition, it seems to be recognised and handled by more browsers types.
Works for NS/Firebird but not for IE.
This is the test code I'm using...
Code: Select all
<?php ob_start();
$file = $_GET["file"];
header("Cache-Control: private\r\n");
header("Content-Type: application/x-zip-compressed\r\n");
header("Content-Disposition: attachment; filename=" . '"' . $file . '"');
readfile($file);
ob_end_flush(); ?>
The file is called with
download.php?file=testFile.zip
Posted: Sat Jan 17, 2004 2:09 pm
by redmonkey
Code: Select all
$file = $_GET["file"];
$mime_type = 'application/x-compress';
$filesize = filesize($file);
header("Content-Type: " . $mime_type);
header("Content-Length: ".$filesize);
header("Content-Disposition: attachment; filename=" . '"' . $file . '"');
header("Content-Transfer-Encoding: binary");
$contents = @readfile($tmpfile);
I have used this and it works for IE,NS,Mozilla without any problems (for me anyway).
I also use 'application/x-compress' as the mime type for zips, I don't know if it makes any difference.
The only other thing is I don't use ob_start(), I had some problems with this perhaps maybe PHP version specific but it ended up throwing the file out twice within one file.
Posted: Sat Jan 17, 2004 2:13 pm
by DuFF
Gen-ik wrote:User clicks on a link to something like download.php?file=fileToDownload and then download.php will spit out the relevant header information and file, and update and database info etc.
Header information? Whats that? Heres how I'm currently doing it:
mapdl.php?id=183
Code: Select all
<?php
$id = $_GET["id"];
//connect
include("dbclass.php");
$db = new dbSQL;
$db->dbConnect();
//increment number of downloads
$query="UPDATE maps SET downloads=downloads+1 WHERE id='$id'";
$db->dbQuery($query, 0);
//get file info
$query2="SELECT * FROM maps WHERE id='$id'";
$r = $db->dbQuery($query2, 1);
$db->dbClose();
//redirect to file
$path = $_SERVER['DOCUMENT_ROOT'] . $r[category] . "/maps/" . $r[file];
$redirect = "Location: $filepath";
?>
Do I need to add anything?
Posted: Sat Jan 17, 2004 2:30 pm
by Gen-ik
Nope that way works as well.
The only reason I use PHP as a 'stream' for any downloads is to keep the location of the actual files secure (not always needed) and also if I use a class() to dynamically build a ZIP file then headers() etc are required.
In your code though you are redirecting directly to the file you want to download which is another way of doing it... and there's nothing wrong with that

Posted: Sat Jan 17, 2004 2:52 pm
by redmonkey
I should point out (and perhaps that is what you are talking about) when you use those headers in IE the initial pop-up asking if you want to save to disk does contain the filename as 'download.php?file=testFile.zip', I have not found a way round this, however when the save dialog opens it should have the correct filename.
My code example above has a small typo, it should be $contents = @readfile($file); and not $contents = @readfile($tmpfile);
Posted: Sat Jan 17, 2004 3:51 pm
by Gen-ik
redmonkey wrote:I should point out (and perhaps that is what you are talking about) when you use those headers in IE the initial pop-up asking if you want to save to disk does contain the filename as 'download.php?file=testFile.zip', I have not found a way round this, however when the save dialog opens it should have the correct filename.
My code example above has a small typo, it should be $contents = @readfile($file); and not $contents = @readfile($tmpfile);
Yep, this is what I was on about
I do need the filename to be correct though (even on IE) so I'm thinking about using mod-rewrite as part of the download... so pointing to something like
downloads/myImages.zip would actually be pointed to
download.php?file=myImages.zip... that would work on all browsers and display the correct filename (in this case myImages.zip) and not (as IE likes to do) the PHP filename.