I'm trying to force a link to download a file as an attachment. This is stuff I have done before but something is going wrong and I'm not sure what it is. The file types I am trying to send as attachments are all mp4 files. Here is what I am doing:
<?php
if(isset($_GET['file']))
{
$file_path = dirname(__FILE__) . "/videos/$_GET[file]";
if(file_exists($file_path))
{
$file_url = "/videos/$_GET[file]";
header ("Content-type: video/mp4");
header("Content-Transfer-Encoding: binary");
header("Content-disposition: attachment; filename=\"".basename($_GET['file']) ."\"");
header("Content-Length: ".filesize($file_path));
echo readfile($file_url);
}
}
?>
As you can see I am checking to see if the file exists before trying to serve it. What happens is I get the file, it's type is correct(MP4 Video) but the file is only around 100 btyes in size. As I was debugging I tested to see if the filesize is correct, it is. I've changed the readfile()
line to:
header("location:/videos/$_GET[file]");
and it takes me to the video. I've done a fair bit of Googling and I havn't come up with a reason for this behavoiur. Has anyone seen this type of thing before? Any ideas on what could be causing this? Any help would be very much appreciated, thanks much!
If you open the contents of that file you downloaded in a text editor, you will no doubt see an error message. This is probably because your path starts with /
. When you open files from disk, the doc root of your server path is meaningless. You need to specify the real path.
Also, your script is terribly insecure! Anyone can download any file they want off your server. Make sure to check that the file is within the doc root before serving it up. Never let a user just specify any file they want without restriction. You don't want some doing ?file=../../../etc/passwd
.
Use these functions, it help you.
function getRemoteFilesize($url)
{
$file_headers = @get_headers($url, 1);
if($size =getSize($file_headers)){
return $size;
} elseif($file_headers[0] == "HTTP/1.1 302 Found"){
if (isset($file_headers["Location"])) {
$url = $file_headers["Location"][0];
if (strpos($url, "/_as/") !== false) {
$url = substr($url, 0, strpos($url, "/_as/"));
}
$file_headers = @get_headers($url, 1);
return getSize($file_headers);
}
}
return false;
}
function getSize($file_headers){
if (!$file_headers || $file_headers[0] == "HTTP/1.1 404 Not Found" || $file_headers[0] == "HTTP/1.0 404 Not Found") {
return false;
} elseif ($file_headers[0] == "HTTP/1.0 200 OK" || $file_headers[0] == "HTTP/1.1 200 OK") {
$clen=(isset($file_headers['Content-Length']))?$file_headers['Content-Length']:false;
$size = $clen;
if($clen) {
switch ($clen) {
case $clen < 1024:
$size = $clen . ' B';
break;
case $clen < 1048576:
$size = round($clen / 1024, 2) . ' KiB';
break;
case $clen < 1073741824:
$size = round($clen / 1048576, 2) . ' MiB';
break;
case $clen < 1099511627776:
$size = round($clen / 1073741824, 2) . ' GiB';
break;
}
}
return $size;
}
return false;
}
usage:
echo getRemoteFilesize('https://stackoverflow.com/questions/14679268/downloading-files-as-attachment-filesize-incorrect');