`
star690178485
  • 浏览: 7002 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
最近访客 更多访客>>
社区版块
存档分类
最新评论

使用Nginx的X-Sendfile机制提升PHP文件下载性能

    博客分类:
  • php
阅读更多
很多时候用户需要从网站下载文件,如果文件是可以通过一个固定链接公开获取的,那么我们只需将文件存放到 webroot 下的目录里就好。但大多数情况下,我们需要做权限控制,例如下载 PDF 账单,又例如下载网盘里的档案。这时,我们通常借助于脚本代码来实现,而这无疑会增加服务器的负担。


例如下面的代码:

<?php
    // 用户身份认证,若验证失败跳转
    authenticate();
    // 获取需要下载的文件,若文件不存在跳转
    $file = determine_file();
    // 读取文件内容
    $content=file_get_contents($file);
    // 发送合适的 HTTP 头
    header("Content-type: application/octet-stream");
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');
    header("Content-Length: ". filesize($file));
    echo $content; // 或者 readfile($file);
?>一、这样做有什么问题?
这样做意味着我们的程序需要将文件内容从磁盘经过一个固定的 buffer 去循环读取到内存,再发送给前端 web 服务器,最后才到达用户。当需要下载的文件很大的时候,这种方式将消耗大量内存,甚至引发 php 进程超时或崩溃。Cache 也很头疼,更不用说中断重连的情况了。

一个理想的解决方式应该是,由 php 程序进行权限检查等逻辑判断,一切通过后,让前台的 web 服务器直接将文件发送给用户——像 Nginx 这样的前台更善于处理静态文件。这样一来 php 脚本就不会被 I/O 阻塞了。

二、什么是 X-Sendfile?
X-Sendfile 是一种将文件下载请求由后端应用转交给前端 web 服务器处理的机制,它可以消除后端程序既要读文件又要处理发送的压力,从而显著提高服务器效率,特别是处理大文件下载的情形下。

X-Sendfile 通过一个特定的 HTTP header 来实现:在 X-Sendfile 头中指定一个文件的地址来通告前端 web 服务器。当 web 服务器检测到后端发送的这个 header 后,它将忽略后端的其他输出,而使用自身的组件(包括 缓存头 和 断点重连 等优化)机制将文件发送给用户。

不过,在使用 X-Sendfile 之前,我们必须明白这并不是一个标准特性,在默认情况下它是被大多数 web 服务器禁用的。而不同的 web 服务器的实现也不一样,包括规定了不同的 X-Sendfile 头格式。如果配置失当,用户可能下载到 0 字节的文件。

使用 X-Sendfile 将允许下载非 web 目录中的文件(例如/root/),即使文件在 .htaccess 保护下禁止访问,也会被下载。

不同的 web 服务器实现了不同的 HTTP 头 sendfile 头 使用的 web 服务器
X-Sendfile Apache, Lighttpd v1.5, Cherokee
X-LIGHTTPD-send-file Lighttpd v1.4
X-Accel-Redirect Nginx, Cherokee

使用 X-SendFile 的缺点是你失去了对文件传输机制的控制。例如如果你希望在完成文件下载后执行某些操作,比如只允许用户下载文件一次,这个 X-Sendfile 是没法做到的,因为后台的 php 脚本并不知道下载是否成功。

三、怎样使用?
Apache 请参考mod_xsendfile模块。下面我介绍 Nginx 的用法。

Nginx 默认支持该特性,不需要加载额外的模块。只是实现有些不同,需要发送的 HTTP 头为 X-Accel-Redirect。另外,需要在配置文件中做以下设定

location /protected/ {
  internal;
  root   /some/path;
}internal 表示这个路径只能在 Nginx 内部访问,不能用浏览器直接访问防止未授权的下载。

于是 PHP 发送 X-Accel-Redirect 给 Nginx:

<?php
    $filePath = '/protected/iso.img';
    header('Content-type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');
    //让Xsendfile发送文件
    header('X-Accel-Redirect: '.$filePath);
?>这样用户就会下载到 /some/path/protected/iso.img 这个路径下的文件。

如果你想发送的是 /some/path/iso.img 文件,那么 Nginx 配置应该是

location /protected/ {
  internal;
  alias   /some/path/; # 注意最后的斜杠


作者:lovelucy
分享到:
评论
1 楼 cvssvn 2013-04-22  
求教,如果想要下载 /some/path/protected/aaa/bbb/iso.img; /some/path/protected/ccc/ddd/iso2.img;
该如何修改配置文件呢?

相关推荐

    在Nginx中使用X-Sendfile头提升PHP文件下载的性能(针对大文件下载)

    在Nginx中使用X-Sendfile头提升PHP文件下载性能是解决大文件下载和权限控制问题的有效策略。传统的PHP文件下载方式会将文件内容读入内存,然后通过HTTP响应发送给用户,对于大文件来说,这可能导致内存压力过大、...

    在PHP中使用X-SendFile头让文件下载更快

    在PHP中,加速文件下载的方法之一是利用X-SendFile技术。这个技术允许你通过Web服务器(如Apache或Nginx)直接向客户端发送文件,从而避免了PHP处理大文件时可能带来的性能瓶颈。以下是对这个知识点的详细解释: 1....

    nginx文件资源下载

    # 使用 sendfile 提高性能 add_header 'Accept-Ranges' 'bytes'; # 支持断点续传 client_max_body_size 100M; # 设置最大允许下载文件大小,可根据需要调整 try_files $uri $uri/ =404; # 如果文件不存在,返回...

    download:通过PHP或X-SendFile从媒体池下载文件的文件

    此加载项将任何文件从媒体池发送到浏览器,作为强制下载。 为了使附加组件正常工作,.htaccess中必须包含以下行: # REWRITE RULE FOR SEO FRIENDLY DOWNLOAD URLS RewriteRule ^download[s]?/([^/]*) index....

    linux下安装Nginx以及配置文件详解

    sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log...

    分享nginx+php-fpm实现大文件下载排坑的过程

    `sendfile`指令用于启用或禁用内核级别的文件传输,启用后能够提高大文件下载的效率;`tcp_nopush`和`tcp_nodelay`能够优化网络包的传输方式,减少数据传输的延迟。 3. 断点续传的实现 断点续传是大文件下载的重要...

    nginx-1.5.17

    4. 性能优化:调整worker_processes的数量以匹配系统资源,优化sendfile、tcp_nopush、tcp_nodelay等参数来提升性能。 四、Nginx与其他技术的集成 1. PHP-FPM:通过fastcgi_pass指令,Nginx可以与PHP-FPM配合,...

    开源电子书:Nginx 开发手册文档.pdf

    9. sendfile 支持:Nginx 支持 sendfile 函数,可以提高文件传输的效率。 Nginx 的安装和配置: 1. 安装 Nginx:可以在 Windows、FreeBSD、Ubuntu、Fedora 等多种操作系统上安装 Nginx。 2. 配置 Nginx:可以使用...

    nginx配置详细-最全说明

    在提供的Nginx配置文件中,我们可以看到很多重要的指令和设置项,这些设置项对于优化Nginx服务性能至关重要。接下来,我们将逐一解析这些配置项的意义及用法。 #### 二、基本配置 1. **`user`**: - **含义**: ...

    nginx安装手册.pdf

    - sendfile指令:是否启用高效文件传输模式。 - keepalive_timeout指令:设置保持连接的超时时间。 - gzip指令:启用或者禁用gzip压缩。 四、Nginx配置实例 - 配置监听80端口的服务器块,处理来自IP为*.*.*.*的请求...

    架构师实战Nginx构建高性能WEB服务器

    - **文件缓存:** 开启sendfile功能,利用操作系统缓存加速文件传输。 - **HTTP压缩:** 启用gzip压缩,减少网络传输量。 - **错误日志:** 调整error_log的级别,避免记录过多无用信息。 - **健康检查:** 设置...

    nginx安装及配置

    Nginx还具备sendfile、sendfile64特性,用于优化文件传输,以及支持异步I/O(AIO)和内存映射(mmap)技术,进一步提升性能。 **Nginx的主要功能** 1. **静态资源服务**:Nginx擅长处理静态文件请求,如HTML、CSS...

    Nginx配置文件说明.

    此外,配置文件还包含了各种超时时间(如`client_header_timeout`,`client_body_timeout`,`send_timeout`)以及性能优化设置(如`sendfile`,`tcp_nopush`,`tcp_nodelay`,`keepalive_timeout`)等。 正确理解和...

    nginx安装包和教程

    sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; ...

    nginx动静态分离,静态文件

    sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 8087; server_name localhost; charset utf-8; #access_log logs/host.access.log main; ...

    nginx运行php的配置(wordpress)

    sendfile on; keepalive_timeout 65; # PHP处理 include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; # 连接php-fpm的端口 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $...

    Linux+nginx+php+mysql+memcache

    - 使用sendfile指令提升文件读取速度。 2. **PHP优化**: - 启用OPcache加速。 - 减少不必要的数据库查询次数。 - 使用对象缓存机制减轻内存负担。 3. **MySQL优化**: - 选择合适的存储引擎(InnoDB、MyISAM...

    nginx安装过程

    sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /usr/local/nginx/html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; ...

Global site tag (gtag.js) - Google Analytics