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

一般来说, 我们可以通过直接让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 . '"');
    }

    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 . '"');
    }

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

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

Lighttpd和Nginx也有类似的模块, 大家有兴趣的可以去找找看

时间: 2024-07-31 13:30:57

在PHP中使用X-SendFile头让文件下载更快_php实例的相关文章

Win7 64位旗舰版中SSD固态硬盘怎么优化才更快

至从固态硬盘的推出,跟机械硬盘老掉牙的速度比起来,SSD固态硬盘称的上是火箭一样的速度了,安装上固态硬盘后Win7系统不管是开机还是运行才有了质的提升,不过很多朋友可能还不知道,使用固态硬盘还有一些需要知道的优化方法,可以让你的固态硬盘在Win7系统中发挥最优性能. 1.安装,安装固态硬盘的时候大家尽量选择插在SATA 3.0的插口上,如果你主板带SATA3.0的话这样能让传输速度更快些; 2.分区,分区的时候可以跟普通硬盘一样分区,不过一些要记得勾选"对齐到下列扇区数的整倍数",然后

大数据处理过程中,如何让Hadoop运行得更快一些?

在数据处理方面,我们发现数据输入速度一般要比的数据处理速度快很多,这种现象在大数据领域尤为明显.随着数据不断膨胀,相应的响应时间自然要有所增加,数据处理的复杂度也在不断提高.作为一个开发者,我们自然非常关注系统的运行速度问题.在云计算领域,一个小技巧也许能带来系统性能的大幅度提升.对于Hadoop来说,如何提升它的速度呢?来看看下文. Hadoop是用以下的方式来解决速度问题: 1 使用分布式文件系统:这使得负载分摊,并壮大系统 2 优化写入速度:为了获得更快的写入速度,Hadoop架构是设计成

PHP中使用GD库创建圆形饼图的例子_php实例

在PHP中,有一些简单的图像函数是可以直接使用的,但大多数要处理的图像,都需要在编译PHP时加上GD库.除了安装GD库之外,在PHP中还可能需要其他的库,这可以根据需要支持哪些图像格式而定.GD库可以在http://www.boutell.com/gd/免费下载,不同的GD版本支持的图像格式不完全一样,最新的GD库版本支持GIF.JPEG.PNG.WBMP.XBM等格式的图像文件,此外还支持一些如FreeType.Type 1等字体库.通过GD库中的函数,可以完成各种点.线.几何图形.文本及颜色

PHP中nowdoc和heredoc使用需要注意的一点_php实例

最后发现了问题所在,原来这类文档在结束时,一定要靠近行的第一位,就是说EOF前面不能有空格,而为了代码缩进,正好产生了这样的问题. 复制代码 代码如下: $str = <<<'EOD'Example of stringspanning multiple linesusing nowdoc syntax.EOD;//EOD一定要靠近前面,不能有空格,同时不要漏掉结束符分号; 附:heredoc和nowdoc的区别 heredoc使用 <<< EOT 的标示符,而nowdo

关于php中的json_encode()和json_decode()函数的一些说明_php实例

一,json语法( php中的json_decode($json)中的$json要符合json语法格式 ) ① JSON可以表示三种类型的值 1,简单值.包括整型,字符串型,布尔值和null.例如:5,"hello world",true,null都是有效的JSON数据.其中JSON字符串必须使用双引号(单引号会导致语法错误). 2,对象.如,{"name":"tony","age":15}.说明①要求属性必须用双引号(不加或

php array_walk 对数组中的每个元素应用用户自定义函数详解_php实例

php array_walk 对数组中的每个元素应用用户自定义函数 array_walk 使用用户自定义函数对数组中的每个元素做回调处理 基本语法 bool array_walk ( array &$array , callable $funcname [, mixed $userdata = NULL ] ) 将用户自定义函数 funcname 应用到 array 数组中的每个单元. array_walk() 不会受到 array 内部数组指针的影响. array_walk() 会遍历整个数组

php中的filesystem文件系统函数介绍及使用示例_php实例

basename - 返回路径中的文件名部分dirname - 返回路径中的目录部分 复制代码 代码如下: string basename ( string $path [, string $suffix ] )string dirname ( string $path ) 示例: 复制代码 代码如下: <?php$path = "/home/httpd/phpha.com/index.php";echo basename($path);echo basename($path,

在Thinkphp中使用ajax实现无刷新分页的方法_php实例

在Thinkphp目录的Lib\ORG\Util\目录里新建AjaxPage.class.php,写入一下内容: <?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK IT ] // +---------------------------------------------------------------

php中sql注入漏洞示例 sql注入漏洞修复_php实例

在开发网站的时候,出于安全考虑,需要过滤从页面传递过来的字符.通常,用户可以通过以下接口调用数据库的内容:URL地址栏.登陆界面.留言板.搜索框等.这往往给骇客留下了可乘之机.轻则数据遭到泄露,重则服务器被拿下.  一.SQL注入的步骤 a)  寻找注入点(如:登录界面.留言板等) b)  用户自己构造SQL语句(如:' or 1=1#,后面会讲解) c)  将sql语句发送给数据库管理系统(DBMS) d)  DBMS接收请求,并将该请求解释成机器代码指令,执行必要的存取操作 e)  DBMS