使用PHP下载大型“私有”文件

时间:2014-06-01 16:53:30

标签: php linux apache centos download

我将私人文件存储在服务器上(Centos / Apache / PHP),授权用户可以使用webbrowser下载(确定用户是否被授权在其他地方,并且不是问题的一部分)。

我使用以下脚本下载文件。它适用于小文件,但是当文件很大(约80MB)时它不起作用。对于这些,下载的文件是零字节,Adobe表示它是非支持类型或由于未编码的电子邮件而损坏。我已经确认服务器上的文件没问题,所以问题不是由我的上传脚本引起的。

什么可能导致此问题以及如何解决?

另外,有更好的方法来限制下载文件吗?我担心的可能是我的上述方法在服务器/ PHP上放置了过多的工作。在目录上放置Apache密码并要求用户输入它不是一个可行的解决方案。不知道是否存在其他东西,但我想我会问。

谢谢

/* Given: $file='/var/www/private/filename'
          $file_name='xx.pdf'
*/
public function dl_file($file,$file_name)
{
    //First, see if the file exists
    if (!is_file($file)) { die('Document does not exist'); }

    //All this function does is get the appropriate mime type    
    $fileInfo=library::getFileInfo(library::getExt($file_name));

    syslog(LOG_INFO,'Content-Type: '.$fileInfo['mime'].' Content-Disposition: attachment; filename="'.$file_name.'" Content-Length: '.filesize($file));
    //Begin writing headers
    header('Pragma: public');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Cache-Control: public');
    header('Content-Description: File Transfer');

    //Use the switch-generated Content-Type
    header('Content-Type: '.$fileInfo['mime']);

    //Force the download
    header('Content-Disposition: attachment; filename="'.$file_name.'"' );
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: '.filesize($file));
    readfile($file);
}

从syslog上面输出:

Jun  1 09:24:15 devserver httpd: Content-Type: application/pdf Content-Disposition: attachment; filename="xx.pdf" Content-Length: 86396350

2 个答案:

答案 0 :(得分:0)

我没有得到答案为什么大文件下载为零大小,但也许我有一个很大的灵感来自https://stackoverflow.com/a/4126882/1032531的替代方案。

首先,我将在公共HTML空间中创建一个名为" private"的目录。

我会在我的页面中放置HTML链接,该链接表示要下载的文件,指向可公开访问的PHP文件,并在URL中包含文件名。

访问后,我将删除私人目录中超过1秒的所有文件。

然后,我将获取文件名并验证用户是否有权下载该文件。

如果获得授权,我将创建一个位于私人目录中的符号链接,该链接指向相关文件,并将其重定向到该符号链接。

似乎合理吗?

我的方法存在一个缺陷,即文件可以在私人目录中公开访问。我可以使用随机名称,但是,我希望使用真实名称下载文件以供授权用户使用。有什么建议吗?

答案 1 :(得分:0)

我认为有三个原因:

  • 您的脚本超出了执行的最长时间

  • intenet的速度,也是下载文件的人 慢。所以你的脚本将超过它的最大持续时间 执行,只要用户尚未完成下载 文件

  • 服务器速度很慢,在这种情况下没什么大不了的

解决您的问题 尝试使用函数:set_time_limit()

**`set_time_limit (int $ seconds ) ;`**

例如set_limit_time尝试(120); 将允许用户下载文件少于120秒

您必须计算下载文件所需的时间,相对于客户的互联网速度以及服务器的速度 添加脚本需要执行的时间

这将是你必须给set_limit_time()函数

的时间

我希望这有帮助

此处有更多信息:http://www.php.net/manual/en/function.set-time-limit.php

为了更安全,请使用mod_xsendfile,这是一个apache模块

mod_xsendfile是一个小型Apache2模块,用于处理原始输出处理程序注册的X-SENDFILE标头。

如果它遇到这样的头部,它将丢弃所有输出并发送该头部指定的文件,而不是使用Apache内部,包括所有优化,如缓存头和sendfile或mmap(如果已配置)。

对于处理例如脚本输出很有用。 php,perl或任何cgi。

有用?

是的,这很有用。

Some applications require checking for special privileges.
Other have to lookup values first (e.g.. from a DB) in order to correctly process a download request.
Or store values (download-counters come into mind).
etc.

优势

Uses apache internals
Optimal delivery through sendfile and mmap (if available).
Sets correct cache headers such as Etag and If-Modified-Since as if the file was statically served.
Processes cache headers such as If-None-Match or If-Modified-Since.
Support for ranges.

访问此链接https://tn123.org/mod_xsendfile/