让PHP更快的提供文件下载的代码


Posted in PHP onJune 13, 2012

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

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

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

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

<?php 
$file = "/tmp/中文名.tar.gz"; 
$filename = basename($file); 
header("Content-type: application/octet-stream"); 
//处理中文文件名 
$ua = $_SERVER["HTTP_USER_AGENT"]; 
$encoded_filename = urlencode($filename); 
$encoded_filename = str_replace("+", "%20", $encoded_filename); 
if (preg_match("/MSIE/", $ua)) { 
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"'); 
} else if (preg_match("/Firefox/", $ua)) { 
header("Content-Disposition: attachment; filename*=\"utf8''" . $filename . '"'); 
} else { 
header('Content-Disposition: attachment; filename="' . $filename . '"'); 
} 
header('Content-Disposition: attachment; filename="' . $filename . '"'); 
header("Content-Length: ". filesize($file)); 
readfile($file);

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

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

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

今天, 我看到了一个有意思的文章: How I PHP: X-SendFile.

我们可以使用Apache的module mod_xsendfile, 让Apache直接发送这个文件给用户:

<?php 
$file = "/tmp/中文名.tar.gz"; 
$filename = basename($file); 
header("Content-type: application/octet-stream"); 
//处理中文文件名 
$ua = $_SERVER["HTTP_USER_AGENT"]; 
$encoded_filename = urlencode($filename); 
$encoded_filename = str_replace("+", "%20", $encoded_filename); 
if (preg_match("/MSIE/", $ua)) { 
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"'); 
} else if (preg_match("/Firefox/", $ua)) { 
header("Content-Disposition: attachment; filename*=\"utf8''" . $filename . '"'); 
} else { 
header('Content-Disposition: attachment; filename="' . $filename . '"'); 
} 
header('Content-Disposition: attachment; filename="' . basename($file) . '"'); 
//让Xsendfile发送文件 
header("X-Sendfile: $file");

X-Sendfile头将被Apache处理, 并且把响应的文件直接发送给Client.
Lighttpd和Nginx也有类似的模块, 大家有兴趣的可以去找找看
PHP 相关文章推荐
ie6 动态缩略图不显示的原因
Jun 21 PHP
PHP学习笔记之一
Jan 17 PHP
php 5.3.5安装memcache注意事项小结
Apr 12 PHP
解析linux下安装memcacheq(mcq)全过程笔记
Jun 27 PHP
PHP正则提取不包含指定网址的图片地址的例子
Apr 21 PHP
浅谈discuz密码加密的方式
May 22 PHP
thinkPHP中多维数组的遍历方法
Jan 09 PHP
php实现搜索类封装示例
Mar 31 PHP
ucenter中词语过滤原理分析
Jul 13 PHP
PHP页面间传递值和保持值的方法
Aug 24 PHP
Yii2实现自定义独立验证器的方法
May 05 PHP
Laravel 5+ .env环境配置文件详解
Apr 06 PHP
深入理解PHP之数组(遍历顺序)  Laruence原创
Jun 13 #PHP
header中Content-Disposition的作用与使用方法
Jun 13 #PHP
php文件打包 下载之使用PHP自带的ZipArchive压缩文件并下载打包好的文件
Jun 13 #PHP
Php中文件下载功能实现超详细流程分析
Jun 13 #PHP
php异常处理技术,顶级异常处理器
Jun 13 #PHP
PHP的异常处理类Exception的使用及说明
Jun 13 #PHP
PHP抽象类 介绍
Jun 13 #PHP
You might like
超外差式晶体管收音机的组装与统调
2021/03/01 无线电
php实现两表合并成新表并且有序排列的方法
2014/12/05 PHP
PHP入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等)
2016/09/11 PHP
PHP经典实用正则表达式小结
2017/05/04 PHP
ThinkPHP5 框架引入 Go AOP,PHP AOP编程项目详解
2020/05/12 PHP
PHP加MySQL消息队列深入理解
2021/02/27 PHP
基于JQuery的cookie插件
2010/04/07 Javascript
初窥JQuery-Jquery简介 入门了解篇
2010/11/25 Javascript
js报错 Object doesn't support this property or method的原因分析
2011/03/31 Javascript
浅谈Javascript事件模拟
2012/06/27 Javascript
JS调用CS里的带参方法实例
2013/08/01 Javascript
引用外部脚本时script标签关闭的写法
2014/01/20 Javascript
js实现图片无缝滚动
2015/12/23 Javascript
jQuery基于muipicker实现仿ios时间选择
2016/02/22 Javascript
JavaScript原生节点操作小结
2017/01/17 Javascript
原生js开发的日历插件
2017/02/04 Javascript
js前端实现图片懒加载(lazyload)的两种方式
2017/04/24 Javascript
jquery submit()不能提交表单的解决方法
2017/04/24 jQuery
深入理解Node中的buffer模块
2017/06/03 Javascript
JavaScript判断变量名是否存在数组中的实例
2017/12/28 Javascript
AngularJS 多指令Scope问题的解决
2018/10/25 Javascript
vue中使用vue-cli接入融云实现即时通信
2019/04/19 Javascript
如何基于layui的laytpl实现数据绑定的示例代码
2020/04/10 Javascript
[01:02:48]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 LGD vs OG
2018/04/02 DOTA
Python安装官方whl包和tar.gz包的方法(推荐)
2017/06/04 Python
通过Py2exe将自己的python程序打包成.exe/.app的方法
2018/05/26 Python
Python XlsxWriter模块Chart类用法实例分析
2019/03/11 Python
python3中利用filter函数输出小于某个数的所有回文数实例
2019/11/24 Python
python装饰器使用实例详解
2019/12/14 Python
任意一块网页内容实现“活”的背景(目前火狐浏览器专有)
2014/05/07 HTML / CSS
推荐10个HTML5响应式框架
2016/02/25 HTML / CSS
家具厂厂长岗位职责
2014/01/01 职场文书
保密工作实施方案
2014/02/24 职场文书
活动总结书
2014/05/08 职场文书
2015重阳节敬老活动总结
2015/07/29 职场文书
直播实况, OMG破敌三路五十分钟大战神技局摩托车
2022/04/01 DOTA