让php更快提供文件下载

一般来说我们可以通过直接让URL指向一个位于Document Root下面的文件来引导用户下载文件.

但是这样做就没办法做一些统计权限检查等等的工作于是很多时候我们采用让PHP来做转发为用户提供文件下载. 

1 <?php
2     $file = "/tmp/dummy.tar.gz";
3     header("Content-type: application/octet-stream");
4     header('Content-Disposition: attachment; filename="' . basename($file) . '"');
5     header("Content-Length: ". filesize($file));
6     readfile($file);

但是这个有一个问题就是如果文件是中文名的话有的用户可能下载后的文件名是乱码.

于是我们做一下修改(参考: :

 1 <?php
 2     $file = "/tmp/中文名.tar.gz";
 3  
 4     $filename = basename($file);
 5  
 6     header("Content-type: application/octet-stream");
 7  
 8     //处理中文文件名
 9     $ua = $_SERVER["HTTP_USER_AGENT"];
10     $encoded_filename = rawurlencode($filename);
11     if (preg_match("/MSIE/", $ua)) {
12      header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
13     } else if (preg_match("/Firefox/", $ua)) {
14      header("Content-Disposition: attachment; filename*=\"utf8''" . $filename . '"');
15     } else {
16      header('Content-Disposition: attachment; filename="' . $filename . '"');
17     }
18  
19     header("Content-Length: ". filesize($file));
20     readfile($file);

现在看起来好多了不过还有一个问题那就是readfile, 虽然PHPreadfile尝试实现的尽量高效不占用PHP本身的内存但是实际上它还是需要采用MMAP(如果支持), 或者是一个固定的buffer去循环读取文件直接输出.

输出的时候如果是Apache + PHP mod, 那么还需要发送到Apache的输出缓冲区最后才发送给用户而对于Nginx + fpm如果他们分开部署的话那还会带来额外的网络IO.

那么能不能不经过PHP这层直接让Webserver直接把文件发送给用户呢?

我们可以使用Apachemodule mod_xsendfileApache直接发送这个文件给用户:

 

 1 <?php
 2     $file = "/tmp/中文名.tar.gz";
 3  
 4     $filename = basename($file);
 5  
 6     header("Content-type: application/octet-stream");
 7  
 8     //处理中文文件名
 9     $ua = $_SERVER["HTTP_USER_AGENT"];
10     $encoded_filename = rawurlencode($filename);
11     if (preg_match("/MSIE/", $ua)) {
12      header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
13     } else if (preg_match("/Firefox/", $ua)) {
14      header("Content-Disposition: attachment; filename*=\"utf8''" . $filename . '"');
15     } else {
16      header('Content-Disposition: attachment; filename="' . $filename . '"');
17     }
18  
19     //让Xsendfile发送文件
20     header("X-Sendfile: $file");

 

X-Sendfile头将被Apache处理并且把响应的文件直接发送给Client. 

 

转载于:https://www.cnblogs.com/lpfuture/archive/2013/02/25/2931676.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值