综述
文件下载一直是PHP的痛,传统的做法是 PHP 读取文件后,通过输出到缓冲区到用户浏览器,这里的弊端显而易见。
首先,PHP-FPM 是堵塞工作的,如果文件比较大,需要耗费一个 PHP 线程处理;
其次,使用 PHP 处理文件下载,非常浪费宝贵的内存空间。
理想的情况下,我们可以采用 云存储 和 CDN 去解决这个问题,但是对于需要验证用户信息的私有文件来说,这里就不适用了。
下面介绍四种方法去解决这个问题
私有文件解决方法:
1、X-Accel:
PHP:
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename="protected.pdf"');
header("X-Accel-Redirect: /protected/protected.pdf");
Nginx:
location /protected/{
internal; # 禁止外部访问
root /files/protected;
}
internal 指令指定某个location只能被“内部的”请求调用,外部的调用请求会返回”Not found” (404)
“内部的”是指下列类型:
• 指令error_page重定向的请求。
• ngx_http_ssi_module模块中使用include virtual指令创建的某些子请求。
• ngx_http_rewrite_module模块中使用rewrite指令修改的请求。
引用:
https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/
https://segmentfault.com/q/1010000002981993
2、Swoole:
上面的方法不是最完美的,因为需要启动一个 PHP 进程来生成 Header,所以,用 swoole 专门处理文件下载这一块,用户验证、下载删除 也很容易做。
3、Nginx-Lua-Redis(大雾):
如果我们不适用 PHP,也是有方法的,下载的连接包含用户的授权token,lua 拿到用户 cookie 的 id 后,查询 reids 的 hash,如果存在token,就放下载,否则返回404.
引用:http://nginx.org/en/docs/http/ngx_http_core_module.html#aio
网友评论