Apache和PHP的选择性文件下载权限

时间:2010-11-10 14:08:05

标签: php apache file download

我有一个带有文件下载选项的网站。但是并不是每个人都可以下载每个文件。例如,如果我以管理员身份登录,我可以下载所有文件,但如果我以客户身份登录,我只能下载某些文件。

目前,所有这些文件都存储在Web根目录之外的目录中,因此用户无法手动下载它们。我制作了一个PHP脚本来管理文件的下载,但它非常错误。我尝试了几件事:

1:

echo file_get_contents($file);

2:

readfile($file);

3:

if (($handle = fopen($file, "rb")) !== false)
{
  while (!feof($handle))
  {
    echo fread($handle, 4096);
  }
  fclose($handle);
}

我发现在使用500MB文件进行测试时,所有这些方法都非常不可靠。第一个和第二个都失败了所有浏览器和随机百分比。有时它们在几兆字节后就已经失败了,而有时它们却达到了80%。但最终他们会在没有任何错误的情况下停止下载。

第三种方法最可靠。它在Firefox中下载得很好(虽然速度太慢;大约700KB / s,而它来自localhost,而readfile方法的工作速度为25MB / s)和Chrome浏览器,但在Internet Explorer中它大多都失败了。在IE中,它首先停留在“获取文件信息”而没有获得任何“打开/保存”对话框。当我取消并再试一次时,我会得到一个“打开/保存”对话框。

我搜索了互联网,但找不到任何令人满意的方法。最好我只是希望Apache处理文件下载,因为它总能正常运行而不会出现问题。但我不想将所有文件放入公共目录,因为每个人都可以下载所有文件。

我有什么选择?有最好的方法吗?

2 个答案:

答案 0 :(得分:2)

1)和2)将打破大文件,因为它们用文件的内容填充脚本的内存。内存限制通常是32或64 MB,并且采取更高的内容是不明智的。

第三种方法应该运行良好,因为它不会填充脚本的内存;但是,请记住发送正确的content-typecontent-length标题。

有一种替代方法可以通过PHP传递文件,我自己没有使用过,但似乎运行良好,X-Sendfile标题。

答案 1 :(得分:0)

有几个选项,包括设置PHP标头,强制下载:

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="example.zip"'); 
header('Content-Transfer-Encoding: binary');

http://www.jonasjohn.de/snippets/php/headers.htm

或者您可以包含链接到相关文件的iFrame ...但不是特别优雅。

这也是一个有趣的教程:

http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/