一个固定的
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 也有类似的模块, 大家有兴趣的可以去找找看