开启DiscuzX/Nginx的附件下载xsendfile支持

正常情况下 一个有鉴权功能的PHP文件下载的时候 要先读文件 然后输出给浏览器 这样的缺点是原本是静态文件 本来可以直接通过nginx就能够返回文件,现在必须通过php,读入内存的东西占用内存不说 php的readfile()函数效率也不高。

我们可以看看DiscuzX在这方面做了什么工作

[php]
if($readmod == 4) {
dheader('Accept-Ranges: bytes');
if(!empty($_SERVER['HTTP_RANGE'])) {
$rangesize = ($filesize - $range) > 0 ? ($filesize - $range) : 0;
dheader('Content-Length: '.$rangesize);
dheader('HTTP/1.1 206 Partial Content');
dheader('Content-Range: bytes='.$range.'-'.($filesize-1).'/'.($filesize));
}
}

function getlocalfile($filename, $readmod = 2, $range = 0) {
if($readmod == 1 || $readmod == 3 || $readmod == 4) {
if($fp = @fopen($filename, 'rb')) {
@fseek($fp, $range);
if(function_exists('fpassthru') && ($readmod == 3 || $readmod == 4)) {
@fpassthru($fp);
} else {
echo @fread($fp, filesize($filename));
}
}
@fclose($fp);
} else {
@readfile($filename);
}
@flush(); @ob_flush();
}[/php]

Discuz定义了许多readmod 下面是官方的介绍

$readmod = 1;
此种模式绝大部分均可支持正常下载,占用资源略高

$readmod = 2;
默认方式,比较节省服务器资源,但是部分服务器可能无法支持,或者只能下载不超过 2M 的文件。

$readmod = 3;
和模式2类似,对资源占用比较小,但是部分服务器可能不支持

$readmod = 4;
支持断点续传,可以保证会员下载大文件的时候成功,且速度更快。但是由于是支持多线程断点续传,
所以服务器的压力也会大一些。此功能可支持绝大部分服务器,但是有个别服务器对资源使用限制较严,
所以您需要测试后再决定是否使用。

可见Discuz在算法上把能用的都用上了 极尽全力优化了下载效率 但是肯定比不上Nginx处理静态文件的效率高。

nginx/Lighthttpd提供了一个高级特性,叫XSendfile,用来读取header信息中的X-Accel-Redirect值,将X-Accel-Redirect所指定的文件内容,作为输出。
这样一来,php就不需要读取文件的正文,只需要输出X-Accel-Redirect值,就可以让nginx负责静态文件的传输了。

dz中的相应代码是

[php]$xsendfile = getglobal('config/download/xsendfile');
if(!empty($xsendfile)) {
$type = intval($xsendfile['type']);
$cmd = '';
switch ($type) {
case 1: $cmd = 'X-Accel-Redirect'; $url = $xsendfile['dir'].$attach['attachment']; break;
case 2: $cmd = $_SERVER['SERVER_SOFTWARE'] <'lighttpd/1.5' ? 'X-LIGHTTPD-send-file' : 'X-Sendfile'; $url = $filename; break;
case 3: $cmd = 'X-Sendfile'; $url = $filename; break;
}
if($cmd) {
dheader("$cmd: $url");
exit();
}
}[/php]

根据代码 模式1是普通的xsendfile 做个别名就好了
模式1是专门为lighttpd/1.5以下的版本写的兼容代码
模式3和模式一不一样 返回的给服务器的是完整路径 不是短路径

我使用了模式1
假设放附件的目录不再bbs的web目录
discuz中配置文件的xsendfile的dir是down

location /down/ {
internal;
alias /data/attachment/forum/;
}

internal表示只供nginx内部访问。

这样就可以了 记得打开Nginx的sendfile功能 参见 http://wiki.nginx.org/XSendfile

Author Info :
  • From:开启DiscuzX/Nginx的附件下载xsendfile支持
  • URL:https://blog.ihipop.com/2011/04/2231.html
  • Please Reserve This Link,Thanks!
  • 《开启DiscuzX/Nginx的附件下载xsendfile支持》上有1条评论

    回复 李惟 取消回复

    您的电子邮箱地址不会被公开。 必填项已用*标注