468,533 Members | 1,947 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,533 developers. It's quick & easy.

Why does readfile($filename) corrupt downloads?

I need to allow users to download files from a directory that is not
publicly accessible. To do this, I use a download script:

header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$filename);
readfile($fullpath);

I've also tried using header("Content-Type: application/force-download")
instead of header("Content-Type: application/octet-stream"), but get the
same results - the downloaded file gets corrupted and cannot be read.

If I move the same file to /public_html and point a link to
http://www.mysite.com/filename.zip, it downloads fine and does not get
corrupted.

Am I using readfile correctly? Is there a more reliable way to download
files from directories that are not publicly accessible?

Thanks in advance.
Jul 17 '05 #1
7 13244
> publicly accessible. To do this, I use a download script:

header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$filename);
readfile($fullpath);

I've also tried using header("Content-Type: application/force-download")
instead of header("Content-Type: application/octet-stream"), but get the
same results - the downloaded file gets corrupted and cannot be read.

If I move the same file to /public_html and point a link to
http://www.mysite.com/filename.zip, it downloads fine and does not get
corrupted.

Am I using readfile correctly? Is there a more reliable way to download
files from directories that are not publicly accessible?


I may have discovered the problem. The page in which the link to the
download script resides is SSL-encrypted. So perhaps the download is going
over an encrypted connection or something. I discovered this by putting the
link to the download script in page that is not SSL-encrypted. The download
works fine from regular page. But this raises another question - how to
download over an SSL connection?
Jul 17 '05 #2
> I may have discovered the problem. The page in which the link to the
download script resides is SSL-encrypted. So perhaps the download is going over an encrypted connection or something. I discovered this by putting the link to the download script in page that is not SSL-encrypted. The download works fine from regular page. But this raises another question - how to
download over an SSL connection?


Correction... with further testing, the issue clearly has something to do
with the download script.

Here is a non-SSL-encrypted page from which the download is initiated:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>
<link href='../../style.css' rel='stylesheet' type='text/css'>
<title>test</title>
</head>
<?php
echo "
<body>
<div id='bodyContent' style='height:800px'>
<table border='0' cellpadding='0' cellspacing='0' width='760'>
<tr>
<td><img src='../../images/headerbar/headerbar1.jpg</td>
<td><img src='../../images/headerbar/headerbar2.jpg'</td>
</tr>
</table>
<!-- <a href='mydirectory/myfile.zip'>myfile.zip</a> -->
<a href='dlcounter.php?file=myfile.zip'>myfile.zip</a>
</div>
</body>
</html>
";
?>

If I swap the commented line with the uncommented line, it works fine. The
way it is now, I get a corrupted download.

The three operative lines in the download script are:

header("Content-Type: application/octet-stream")
header("Content-Disposition: attachment; filename=".$filename);
readfile($fullpath);

Could the issue be the HTTP variable ?file=myfile.zip?
Perhaps the variables I'm using in the download script?
Some aberrant headers somewhere?
Jul 17 '05 #3
*** deko wrote/escribió (Mon, 14 Mar 2005 04:32:27 GMT):
I need to allow users to download files from a directory that is not
publicly accessible. To do this, I use a download script:

header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$filename);
readfile($fullpath);

I've also tried using header("Content-Type: application/force-download")
instead of header("Content-Type: application/octet-stream"), but get the
same results - the downloaded file gets corrupted and cannot be read.


Make you sure aren't adding any extra blanks. The <? and ?> tags should be
the first and last chars in the script file respectively.
Jul 17 '05 #4
deko wrote:
I need to allow users to download files from a directory that is not
publicly accessible. To do this, I use a download script:

header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$filename);
readfile($fullpath);


http://nl.php.net/manual/en/function.fpassthru.php

I used this yesterday for downloading a 100MB protected file (binary is
no problem) over https:

<?php

$file = '100mb.bin';
$fp = fopen($file, 'rb');

header("Content-Type: application/octet-stream");
header("Content-Length: " . filesize($file));

fpassthru($fp);
exit;

?>

--
"He who asks a question is a fool for five minutes;
he who does not ask a question remains a fool forever"
Jul 17 '05 #5
> Make you sure aren't adding any extra blanks. The <? and ?> tags should be
the first and last chars in the script file respectively.


I may discovered the problem. I was trying to use the same download script
for "secure" and "public" downloads, like this:

<?php
session_start();
$filename = trim($_GET[file]);
if ($_SESSION['uid'])
{
$file = '/home/myacct/secure/'.$_SESSION['uid'].'/'.$filename;
}
else
{
$file = 'http://www.clearpointsystems.com/publicdownload/'.$filename;
}
header("Content-Disposition: attachment; filename=".$filename);
header("Content-Length: ".filesize($filename));
readfile($filename);
exit;

I just tried this, and it appeared to work:

<?php
header("Content-Disposition: attachment;
filename=/home/myacct/secure/test.zip");
header("Content-Length: ".filesize('home/myacct/secure/test.zip'));
readfile("home/myacct/secure/test.zip");
?>

Perhaps the problem was the headers getting screwed up with session_start.
Nevertheless, I'm wondering if readfile() will work the same with binary and
text files. Do I need to do anything differently for binary files?
Jul 17 '05 #6
*** deko wrote/escribió (Thu, 17 Mar 2005 05:13:26 GMT):
<?php
session_start();
$filename = trim($_GET[file]);
if ($_SESSION['uid'])
{
$file = '/home/myacct/secure/'.$_SESSION['uid'].'/'.$filename;
}
else
{
$file = 'http://www.clearpointsystems.com/publicdownload/'.$filename;
}
header("Content-Disposition: attachment; filename=".$filename);
header("Content-Length: ".filesize($filename));
readfile($filename);
exit;


You don't use variable $file, do you?
--
-- Álvaro G. Vicario - Burgos, Spain
-- Don't e-mail me your questions, post them to the group
--
Jul 17 '05 #7
> > <?php
session_start();
$filename = trim($_GET[file]);
if ($_SESSION['uid'])
{
$file = '/home/myacct/secure/'.$_SESSION['uid'].'/'.$filename;
}
else
{
$file = 'http://www.clearpointsystems.com/publicdownload/'.$filename;
}
header("Content-Disposition: attachment; filename=".$filename);
header("Content-Length: ".filesize($filename));
readfile($filename);
exit;


You don't use variable $file, do you?


air code error...

$filename should be $file in the last few lines.

In any case, I got it working. I wrote a download script just for secure
downloads and put the download script in cgi-bin and call it from the
SSL-encrypted private page. The private files are located outside of
document root, so I guess it's about as secure as it can get, or at least as
secure as it needs to be. Raj Shekhar sent me something about Pear - I
looked at the web page and tried to read the manual but I still have no idea
what Pear is or why I should use it.
Jul 17 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by Kornelius Finkenbein | last post: by
2 posts views Thread by Matthew Sims | last post: by
1 post views Thread by Jørn Dahl-Stamnes | last post: by
4 posts views Thread by B Squared | last post: by
reply views Thread by defogm | last post: by
2 posts views Thread by Frank Moyles | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.