文档章节

PHP X-sendfile实现文件下载

frylan
 frylan
发布于 2013/06/18 10:17
字数 551
阅读 2487
收藏 5

项目中涉及到文件的下载功能,通常PHP文件下载都是将文件先读取出来然后发送相应头文件进行下载。
如:

$file_dir = $instance->_attach_path.Helper_Hash::hashDIR($id).$attach['path'];
if(!file_exists($file_dir)){
	throw new FromMeException('文件不存在');
}
else{
	// 打开文件
	$file = fopen($file_dir,"r"); 
	// 输入文件标签
	Header("Content-type: application/octet-stream");
	Header("Accept-Ranges: bytes");
	Header("Accept-Length: ".filesize($file_dir));
	Header("Content-Disposition: attachment; filename=" . $attach['name']);
	// 输出文件内容
	echo fread($file,filesize($file_dir));
	fclose($file);
	exit();
}
这种方式可以实现文件的下载,但是这种下载方式相当耗资源,长期占用服务端脚本资源和服务器内存资源,消耗很大。
后来查阅资料,我们可以借助X-sendfile模块来实现更高效率的文件下载。
X-sendfile是现代操作系统支持的一种高性能网络IO方式,服务端脚本程序比如php负责构造请求头信息,然后下载的时候不需要php参与,web服务器直接处理X-Sendfile头信息,并且把响应的文件直接发送给浏览器客户端;这样避免了内存占用。

首先我们要查看Apache的版本信息:


然后下载对应的X-sendfile模块包(下载地址:https://github.com/nmaier/mod_xsendfile)。
1、将解压出来的mod_xsendfile.so文件拷贝到Apache的modules目录下
2、配置Apache的conf目录下的httpd.conf文件,加入以下代码:

LoadModule xsendfile_module modules/mod_xsendfile.so

XSendFile on
XSendFilePath F:/
3、重启Apache服务,访问phpinfo()查看是否加载xsendfile模块:



这些工作完成之后我们就可以借助X-sendfile来实现文件下载了:
$file_dir = $instance->_attach_path.Helper_Hash::hashDIR($id).$attach['path'];
if(!file_exists($file_dir)){
	throw new FromMeException('文件不存在');
}
else{
	
	$ua = $_SERVER["HTTP_USER_AGENT"];
	
	$filename = $attach['name'];
	$encoded_filename = urlencode($filename);
	$encoded_filename = str_replace("+", "%20", $encoded_filename);
   
	// 输入文件标签
	$realpath =  realpath($file_dir);
	header('Content-Type: application/octet-stream');
	
	
	//处理中文文件名,避免文件名乱码
	$encoded_filename = rawurlencode($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 . '"');
	}
	
	//让Xsendfile发送文件
	header("X-Sendfile: $realpath");
	exit();
}

需要注意的是:X-sendfile发送的文件路径要是绝对路径,不然会找不到。

参考文章: 借助X-sendfile模块实现文件下载速度和性能优化

© 著作权归作者所有

共有 人打赏支持
frylan
粉丝 4
博文 22
码字总数 11244
作品 0
南昌
程序员
私信 提问
加载中

评论(1)

雾里看花111
可是这个怎么使用呢
让PHP更快的提供文件下载

一般来说, 我们可以通过直接让URL指向一个位于Document Root下面的文件, 来引导用户下载文件. 但是, 这样做, 就没办法做一些统计, 权限检查, 等等的工作. 于是, 很多时候, 我们采用让PHP来做...

hejunyi1204
2014/11/11
0
0
让 PHP 更快的提供文件下载

一般来说, 我们可以通过直接让URL指向一个位于Document Root下面的文件, 来引导用户下载文件. 但是, 这样做, 就没办法做一些统计, 权限检查, 等等的工作. 于是, 很多时候, 我们采用让PHP来做...

虫虫
2012/05/02
2.5K
11
在nginx中用X-Accel-Redirect response header控制文件下载

在web应用中,常常会有文件需要下载。如果这些文件是非常私密的,直接用web服务器下载,就不能检查文件的下载权限。以往遇到这种需要权限的情况,都是用程序语言判定权限后,使用程序语言来读...

DongHenry
2013/07/08
0
0
强制保存文件的方法(比如jpg,php等)

php自带的方法需要将文件读入然后输出,如果遇到过大文件就会有问题 鸟哥写的:http://www.laruence.com/2012/05/02/2613.html 用apache举例 nginx做法:https://www.markdream.com/technol...

爬墙
2016/04/14
10
0
Linux零拷贝函数SendFile应用

项目需要,使用linux零拷贝函数SendFile来传输文件。 传统的read/write方式进行网络文件传输的方式,要经过四次copy操作: 硬盘 >> kernel buffer >> user buffer >> kernel socket buffer ......

zidanzzg
2016/12/27
14
2

没有更多内容

加载失败,请刷新页面

加载更多

快速开发android,离不开这10个优秀的开源项目

作为一名菜鸡Android,时常瞻仰大佬们的开源项目是非常必要的。这里我为大家收集整理了10个优秀的开源项目,方便我们日常开发中学习! 作者:ListenToCode 博客:https://www.jianshu.com/p...

终端研发部
12分钟前
0
0
MiniUi tab页

architect刘源源
13分钟前
0
0
uitextview中'\n'不能换行的问题

后端返回的类似于这样的东西:'1、Fix bug;\n2、体验优化' 在textview里边是无法换行的,打断点发现 是因为 '\n'被转义成了'\\n'了 思路是replace。。。 _infoTextView.text = [self.info st...

RainOrz
18分钟前
0
0
年底了,该给自己写个总结了,一个六年女Java程序员的心声

简单的先说一下,坐标杭州,12届本科毕业,算上年前在阿里巴巴B2B事业部的面试,一共有面试了有6家公司(因为不想请假,因此只是每个晚上去其他公司面试,所以面试的公司比较少) 其中成功的...

Java架构资源分享
22分钟前
2
0
Shell脚本——cat/EOF输出多行

在某些场合,可能我们需要在脚本中生成一个临时文件,然后把该文件作为最终文件放入目录中。(可参考ntop.spec文件)这样有几个好处,其中之一就是临时文件不是唯一的,可以通过变量赋值,也...

吴伟祥
23分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部