下载大型「;“私人”;使用PHP的文件

下载大型「;“私人”;使用PHP的文件,php,linux,apache,centos,download,Php,Linux,Apache,Centos,Download,我将私有文件存储在服务器上(Centos/Apache/PHP),授权用户可以使用webbrowser下载这些文件(确定用户是否获得授权在其他地方有涉及,这不是问题的一部分) 我使用以下脚本下载该文件。它适用于小文件,但是,当文件很大(~80MB)时,它就不起作用了。对于这些,下载的文件是零字节,Adobe说它要么是不受支持的类型,要么是由于未编码的电子邮件而损坏的。我已经确认服务器上的文件没有问题,所以问题不是由我的上传脚本引起的 什么可能导致此问题?如何解决 还有,有没有更好的方法来限制下载

我将私有文件存储在服务器上(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);
}
以上系统日志的输出:

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

我不知道为什么下载的大文件都是零大小的,但也许我有另一个选择,这是深受启发的

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

我将把链接放在我的网页HTML中,它表示要下载的文件,指向一个可公开访问的PHP文件,并在URL中包含文件名

一旦被访问,我将删除私有目录中早于1秒的所有文件

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

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

看起来合理吗


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

我认为有三个原因:

  • 您的脚本超出了其执行的最大持续时间

  • 互联网的速度,在下载文件的人中也是如此 慢点。因此,您的脚本将超过其最大持续时间 执行,只要用户尚未完成下载 文件

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

解决你问题的办法 尝试使用函数:设置时间限制()

例如设置限制时间(120); 将允许用户下载文件的时间少于120秒

您必须计算您需要下载文件的时间,这与客户的互联网速度和服务器速度有关 添加脚本需要执行的时间

这就是你必须给set_limit_time()函数的时间

我希望这有帮助

更多信息请点击此处:

为了更安全,请使用modxsendfile,它是一个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.

访问此链接

感谢您的帖子。我已经修改了设置时间限制,这不是问题所在。我对mod_xsendfile不太了解,我会尝试一下。这不是问题所在,然后看看脚本使用的最大ram,它有一个最大大小。你是说
内存限制=128M
?我把它提高到了1024M,但没有区别。增加内存限制似乎是可行的。如果我不学习PHP和使用符号链接会更好,我仍然很感兴趣,但眼前的问题已经解决了。感谢您的帮助i tink更好的解决方案是使用缓冲区,我忘记了第一次使用缓冲区,但下面是一个代码示例:
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.