PHP做文件下载服务解决方案

要求:

  1. 文件有权限验证。
  2. 文件大小可能会很大。
  3. 性能要好。

传统做法一:直接源始地址下载

就是直接给出文件的地址 http://www.xxx.com/file.rar,这种方式最直接,性能好,文件大小无限制,但没办法做权限验证。

传统做法二:PHP中转下载

例子代码:

header("Content-Type:application/octet-stream;charset=utf-8");
header('Content-Disposition: attachment; filename=file.rar');
readfile('/www/file.rar');

这种方式是将文件先读取到内存然后转发给用户,可以方便的做权限验证,但性能不好,会占用较大的内存,对大文件支持也不好,会超时。下载人数多服务器还可能会崩溃,因为每次都要把文件读到内存里。

当然有优化内存的方式:

header("Content-Type:application/octet-stream;charset=utf-8");
header('Content-Disposition: attachment; filename=file.rar');
$data = fopen('/www/file.rar', 'rb');
while (!feof($data)) {
       echo @fread($data, 8192);
       ob_flush();
       flush();
}
fclose($data);

但治标不治本,大文件还是会超时,因为大文件下载耗时,超过了php最大执行时间。

当当当当~

新的做法:PHP与Nginx的X-Accel-Redirect配合方案

熟悉Nginx的朋友知道Nginx有个sendfile零拷贝技术,这个技术很厉害,静态文件下载不用占用内存,具体技术可参考https://37wiki.37wan.com/pages/viewpage.action?pageId=10650822

我们现在介绍的这个技术叫x-sendfile,它的原理是:服务端脚本程序(如php)负责处理用户请求,并构造响应头信息,然后文件下载的时候转发给Web服务器(如Nginx)处理,服务端脚本程序不再参与,由Web服务器把具体的文件直接发送给浏览器客户端,而且用sendfile零拷贝技术,避免了内存占用。

这个功能在Apache、Lighttpd叫x-sendfile,在Nginx上叫X-Accel-Redirect。

具体做法如下:
nginx配置文档

location /download
{
   /* 声明为内部,只能nginx内部访问,用户是访问不了这个location的*/
    internal;
    root /www/download;
}

php代码:

header("Content-Type:application/octet-stream;charset=utf-8");
header('Content-Disposition: attachment; filename=file.rar');
header('X-Accel-Redirect: /download/file.rar');

这样Nginx会自动处理X-Accel-Redirect头要求的文件。

整个方案满足上面三点要求:

  1. 文件有权限验证。
  2. 文件超大不会导致php超时。
  3. 性能好,不占用内存。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值