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

很多时候用户需要从网站下载文件,如果文件是可以通过一个固定链接公开获取的,那么我们只需将文件存放到 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;
}

表示这个路径只能在 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/; # 注意最後的斜杠
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索nginx
, X-Sendfile头
PHP文件下载
nginx sendfile、nginx sendfile 作用、nginx sendfile on、nginx sendfile off、nginx sendfile 关闭,以便于您获取更多的相关知识。

时间: 2024-10-22 10:09:26

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

Nginx中404页面的配置及AJAX请求返回404页面的方法_nginx

404页面基础配置404错误是WWW网站访问容易出现的错误.最常见的出错提示:404 NOT FOUND.404错误页的设置对网站SEO有很大的影响,而设置不当,比如直接转跳主页等,会被搜索引擎降权拔毛.404页面的目的应该是告诉用户:你所请求的页面是不存在的,同时引导用户浏览网站其他页面而不是关掉窗口离去.搜索引擎通过HTTP状态码来识别网页的状态.当搜索引擎获得了一个错误链接时,网站应该返回404状态码,告诉搜索引擎放弃对该链接的索引.而如果返回200或302状态码,搜索引擎就会为该链接建立

Nginx中的用户认证配置及阻止用户使用代理访问的方法_nginx

nginx用户认证配置( Basic HTTP authentication)ngx_http_auth_basic_module模块实现让访问着,只有输入正确的用户密码才允许访问web内容.web上的一些内容不想被其他人知道,但是又想让部分人看到.nginx的http auth模块以及Apache http auth都是很好的解决方案. 默认情况下nginx已经安装了ngx_http_auth_basic_module模块,如果不需要这个模块,可以加上 --without-http_auth_

nginx中隐藏响应头/返回头信息/php版本号/服务器信息

首先隐藏nginx版本信息,只需编辑 nginx.conf 文件 添加一行  代码如下 复制代码 server_tokens off; http {     include       /etc/nginx/mime.types;     default_type  application/octet-stream;     index index.php index.html index.htm;     server_tokens off;       log_format  main  '

详解Nginx中的geo模块与利用其配置负载均衡的示例_nginx

geo指令使用ngx_http_geo_module模块提供的.默认情况下,nginx有加载这个模块,除非人为的 --without-http_geo_module. ngx_http_geo_module模块可以用来创建变量,其值依赖于客户端IP地址.geo指令语法: geo [$address] $variable { ... } 默认值: - 配置段: http 定义从指定的变量获取客户端的IP地址.默认情况下,nginx从$remote_addr变量取得客户端IP地址,但也可以从其他变量

http响应Last-Modified和ETag以及Apache和Nginx中的配置

 基础知识 1) 什么是"Last-Modified"? 在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样: Last-Modified: Fri, 12 May 2006 18:53:33 GMT 客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过: If-

Nginx中 Rewrite规则的学习笔记

路由重写是Web服务器中的一个很重要的基本功能.通过路由重写,可以结构化URL,更具语义化(对SEO有益).另外,分享出去的URL可能会因程序路由变动而导致URL失效,而路由的重写可以很好的解决这类问题. 适当的使用Rewrite功能,可以更我们带来很多的好处.Nginx中Rewrite的功能是基于perl语言兼容的正则表达式,所以在编译安装nginx之前,需要安装PREC库.Nginx中Rewrite功能实现是基于ngx_http_rewrite_module,所以确保安装了此模块. Rewr

在Nginx中增加对OAuth协议的支持的教程_nginx

我们使用Nginx的Lua中间件建立了OAuth2认证和授权层.如果你也有此打算,阅读下面的文档,实现自动化并获得收益. SeatGeek在过去几年中取得了发展,我们已经积累了不少针对各种任务的不同管理接口.我们通常为新的展示需求创建新模块,比如我们自己的博客.图表等.我们还定期开发内部工具来处理诸如部署.可视化操作及事件处理等事务.在处理这些事务中,我们使用了几个不同的接口来认证:     Github/Google Oauth     我们SeatGeek内部的用户系统     基本认证  

Nginx中禁止使用IP访问网站的配置实例_nginx

国内因为备案的原因,所有服务器都要禁止使用IP访问网站.否则,如果允许使用IP访问网站,那随便解析一个域名到该IP,访问该域名就可以打开网站了.这是一个极大的风险!Nginx中可以很方便的来解决这个问题,小菜鸟来跟大家一起探讨一下. 国内因为备案的原因,所有服务器都要禁止使用IP访问网站.否则,如果允许使用IP访问网站,那随便解析一个域名到该IP,访问该域名就可以打开网站了.这是一个极大的风险!Nginx中可以很方便的来解决这个问题,小菜鸟来跟大家一起探讨一下. 如下的配置项,可以设置允许使用I

Eclipse中如何自动添加头文件(add include)

在使用Eclipse写程序时, 经常遇到需要找头文件的问题, 在Eclipse中, 包含自动添加头文件的功能; 可以在Java, C++等插件中, 自动添加; 位置: Source -> Add Include (Ctrl+Shift+N): 作者:csdn博客 u012515223 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/Java/