php使用X-SendFile头加速文件下载

在PHP中让文件下载更快的一个方法,那就是使用X-SendFile头实现,主流量的服务器都支持这个头文件。

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

于是, 很多时候, 采用让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 = 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 . ‘"‘);
} www.jbxue.com

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 = 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 . ‘"‘);
} www.jbxue.com

//让Xsendfile发送文件
header("X-Sendfile: $file");

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

Lighttpd和Nginx也有类似的模块,大家可以研究下。

php使用X-SendFile头加速文件下载,布布扣,bubuko.com

时间: 2024-10-05 06:05:31

php使用X-SendFile头加速文件下载的相关文章

实现HTTP文件下载

[原文:http://www.jb51.net/article/89958.htm] HTTP实现文件下载时,只要在服务器设置好相关响应头,并使用二进制传输文件数据即可,而客户端(浏览器)会根据响应头接收文件数据.而在Node.js中,设置好响应头后,读取文件流,再使用“.pipe()”方法将流转接到响应对象Response就可以实现一个简单的文件下载服务器. 1. 文件下载介绍 HTTP基于请求头和响应头实现状态交互,在得到服务器正确响应状态后,而客户端首先会解析响应头,并根据响应头来接收和展

Header实现文件下载

1 function download($file){ 2 //文件根路径 3 $filename=$_SERVER['DOCUMENT_ROOT'].__ROOT__.'/'.$file; 4 //下载文件 5 if(!file_exists($filename)){ 6 $this->error("找不到文件"); 7 exit; 8 }else{ 9 header("Content-Type:text/html;charset=utf-8"); 10 h

20160314 Request 和Response

一.Response 1.Resonse的继承结构: ServletResponse--HttpServletResponse 2.Response代表响应,于是响应消息中的 状态码.响应头.实体内容都可以由它进行操作,由此引伸出如下实验: 3.利用Response输出数据到客户端 response.getOutputStream().write("中文".getBytes())输出数据,这是一个字节流,是什么字节输出什么字节,而浏览器默认用平台字节码打开服务器发送的数据,如果服务器端

request&amp;response

HttpServletRequest&HttpServletResponse. web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象和代表响应的response对象.如果要获取客户机提交的数据,只需要request对象,要想客户机输出数据,只需要response对象. 一.Response    1.Resonse的继承结构:            ServletResponse--HttpServletResponse    2.Response

JavaWeb-Response对象

JavaWeb-Response对象 一.Response 1.Resonse的继承结构: ServletResponse–HttpServletResponse 2.Response代表响应 于是响应消息中的 状态码.响应头.实体内容都可以由它进行操作 3.利用Response输出数据到客户端 response.getOutputStream().write("中文".getBytes()) 输出数据,这是一个字节流,是什么字节输出什么字节, 而浏览器默认用平台字节码打开服务器发送的

nginx服务+LEMP搭建

Nginx nginx的配置运行需要pcre.zlib等软件包支持.所以先搭建好环境,确保nginx安装顺利.以红冒企业版RHEL6为例,搭建Nginx. yum -y install pcre-devel zlib-devel 创建运行用户.组 useradd -M -s /sbin/nologin nginx 解压文件,编译安装.指定安装用户.组.模块等 tar zxf nginx-1.0.8.tar.gz  cd nginx-1.0.8 ./configure --prefix=/usr/

request,response,URL编码,路径专题

一.Response 1.Resonse的继承结构: ServletResponse--HttpServletResponse 2.Response代表响应,于是响应消息中的 状态码.响应头.实体内容都可以由它进行操作,由此引伸出如下实验: 3.利用Response输出数据到客户端 response.getOutputStream().write("中文".getBytes())输出数据,这是一个字节流,是什么字节输出什么字节,而浏览器默认用平台字节码打开服务器发送的数据,如 果服务器

Servlet中Request和Response 详解

一.Response 1.Resonse的继承结构:   ServletResponse--HttpServletResponse 2.Response代表响应,于是响应消息中的 状态码.响应头.实体内容都可以由它进行操作,由此引伸出如下实验: 3.利用Response输出数据到客户端  response.getOutputStream().write("中文".getBytes())输出数据,这是一个字节流,是什么字节输出什么字节,而浏览器默认用平台字节码打开服务器发送的数据,如果服

Servlet中Request与Response应用

一.Response 1.Resonse的继承结构:   ServletResponse--HttpServletResponse 2.Response代表响应,于是响应消息中的状态码.响应头.实体内容都可以由它进行操作,由此引伸出如下实验: 3.利用Response输出数据到客户端  response.getOutputStream().write("中文".getBytes())输出数据,这是一个字节流,是什么字节输出什么字节,而浏览器默认用平台字节码打开服务器发送的数据,如果服务