文档章节

PHP X-sendfile实现文件下载

frylan
 frylan
发布于 2013/06/18 10:17
字数 551
阅读 2473
收藏 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.3K
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
php nginx fastdfs 下载文件重命名

其实fdfs可以传入一个filename参数,指定文件名。。 M00/00/00/fwAAAVGMateAafjTAAAABBW-xbM368.txt?filename=test.txt 这样下载时用户将得到test.txt文件名啦。 ////以下内容仅供娱乐 首先搭...

吾爱
2013/05/10
0
4

没有更多内容

加载失败,请刷新页面

加载更多

MySQL autocommit探究

-- sessionA:tx_isolation=REPEATABLE-READmysql> select connection_id();+-----------------+| connection_id() |+-----------------+| 28 |+-----------------+......

安小乐
4分钟前
4
0
c++多线程锁 Mutex  自动判断死锁

c++多线程锁可以使用absl::Mutex std::mutex这两种,下面是demo代码。 使用absl:Mutex的时候打印: [mutex.cc : 1338] RAW: Cycle: [mutex.cc : 1352] RAW: mutex@0x683b68 stack: @ 0x43856......

青黑
23分钟前
1
0
Blockathon2018(成都站)比赛落幕,留给我们这些区块链应用思考

9月14日,HiBlock区块链社区主办的第二届Blockathon在成都菁融国际广场成功举行,30名参赛者分为5支队伍在48小时内完成区块链项目的创意、开发及路演,经过紧张的开发及现场评选,最终币托(...

HiBlock
28分钟前
0
0
71.告警系统主脚本 配置文件 监控项目

20.20 告警系统主脚本(main.sh) 20.21 告警系统配置文件 20.22 告警系统监控项目 20.20 告警系统主脚本(main.sh): ~1.约定:把以后所有的shell脚本放在/usr/local/sbin下,也方便我们查...

王鑫linux
35分钟前
0
0
装饰者模式

装饰者模式 Q:何为装饰模式? ()地给一个对象添加一些额外的(),并且()时,并不影响原对象。扩展功能来说,装饰器模式相比生成子类更为灵活。 Q:使用场景? 1.想要在不影响其他对象的情况下...

阿元
55分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部