在linux上使用mod_xsendfile用PHP下载大文件


Downloading large files with PHP using mod_xsendfile on linux

我需要使用PHP和身份验证从我的Web服务器提供非常大的文件(1Gb+),这样只有一些客户有权下载文件。

我不想使用直接链接,并且由于内存和超时限制,使用PHP脚本来提供文件不是一个选项。

我的Web服务器使用Plesk进行管理,并在Apache/CentOS 6上运行。

选择的解决方案是在Centos服务器上安装mod_xsendfile,对其进行配置,并在用户身份验证后发送带有PHP头的文件。

在Centos上安装mod_xsendfile。您需要启用EPEL存储库来获取xsendfile,然后是一个简单的:

yum update
yum install mod_xsendfile

之后,您可以使用检查模块是否正确安装

apachectl -M | grep xsendfile

配置/Plesk部分。Plesk会自动生成每个httpd.conf文件,因此手动修改文件是危险的,因为通过Plesk UI进行的任何更改都可能覆盖这些文件。默认情况下,http.conf文件包括vhost.conf和vhostrongsl.conf,对于存储在中的虚拟主机

/var/www/vhosts/system/[yourvhostname]/conf

您可以通过ssh或使用Plesk UI界面(vhost->serversettings->其他apache指令)编辑它们。对于非Plesk用户,只需在httpd.conf 的正确vhost部分下添加以下指令

第一次我遇到一些问题是因为服务器发送了0字节的文件,经过一些测试,我发现正确的指令是:

<Directory "/">
    EnableSendfile on
    XSendFile on
    # Absolute path, no trailing slash!
    XSendFilePath "/var/www/vhosts/[yourvhostname]/storage"
</Directory>

注意,如果我使用与"/"不同的目录指令,我会得到空文件,并且在任何日志上都没有任何错误。没有通过在标头中传递相对路径来测试会发生什么。

因为我使用Laravel作为PHP框架,然后可以使用将文件发送给用户

   return response(null)
       ->header('Content-Type' , 'application/octet-stream')
       ->header('Content-Disposition', 'attachment; '.$filename)
       ->header('X-Sendfile', $fullfilepath);

希望这能帮助人们避免数小时的测试。

Dario上面的评论真的很有帮助。我只是想添加我用于Laravel返回语句的内容,以确保文件的名称正确:

return response(null)
    ->header('Content-Type' , 'application/octet-stream')
    ->header('Content-Disposition', 'attachment; filename="' . $filename . "')
    ->header('X-Sendfile', $fullfilepath);