一般来说, 我们可以通过直接让URL指向一个位于Document Root下面的文件, 来引导用户下载文件.

但是, 这样做, 就没办法做一些统计, 权限检查, 等等的工作.  于是,  很多时候,  我们采用让PHP来做转发, 为用户提供文件下载.

  1. <?php
  2. $file = "/tmp/dummy.tar.gz";
  3. header("Content-type: application/octet-stream");
  4. header('Content-Disposition: attachment; filename="' . basename($file) . '"');
  5. header("Content-Length: ". filesize($file));
  6. readfile($file);

但是这个有一个问题, 就是如果文件是中文名的话, 有的用户可能下载后的文件名是乱码.

于是, 我们做一下修改(参考: :

  1. <?php
  2. $file = "/tmp/中文名.tar.gz";
  3. $filename = basename($file);
  4. header("Content-type: application/octet-stream");
  5. //处理中文文件名
  6. $ua = $_SERVER["HTTP_USER_AGENT"];
  7. $encoded_filename = rawurlencode($filename);
  8. if (preg_match("/MSIE/", $ua)) {
  9. header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
  10. } else if (preg_match("/Firefox/", $ua)) {
  11. header("Content-Disposition: attachment; filename*=\"utf8''" . $filename . '"');
  12. } else {
  13. header('Content-Disposition: attachment; filename="' . $filename . '"');
  14. }
  15. header("Content-Length: ". filesize($file));
  16. 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直接发送这个文件给用户:

  1. <?php
  2. $file = "/tmp/中文名.tar.gz";
  3. $filename = basename($file);
  4. header("Content-type: application/octet-stream");
  5. //处理中文文件名
  6. $ua = $_SERVER["HTTP_USER_AGENT"];
  7. $encoded_filename = rawurlencode($filename);
  8. if (preg_match("/MSIE/", $ua)) {
  9. header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
  10. } else if (preg_match("/Firefox/", $ua)) {
  11. header("Content-Disposition: attachment; filename*=\"utf8''" . $filename . '"');
  12. } else {
  13. header('Content-Disposition: attachment; filename="' . $filename . '"');
  14. }
  15. //让Xsendfile发送文件
  16. header("X-Sendfile: $file");

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

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

原文地址:http://www.laruence.com/2012/05/02/2613.html

让PHP更快的提供文件下载 【转】的更多相关文章

  1. 让PHP更快的提供文件下载

    一般来说, 我们可以通过直接让URL指向一个位于Document Root下面的文件, 来引导用户下载文件. 但是, 这样做, 就没办法做一些统计, 权限检查, 等等的工作. 于是, 很多时候, 我们 ...

  2. php提供更快的文件下载

    在微博上偶然看到一篇介绍php更快下载文件的方法,其实就是利用web服务器的xsendfile特性,鸟哥的博客中只说了apache的实现方式,我找到了介绍nginx实现方式的文章,整理一下! let' ...

  3. QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用

    FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QL ...

  4. 更轻更快的Vue.js 2.0与其他框架对比(转)

    更轻更快的Vue.js 2.0 崭露头角的JavaScript框架Vue.js 2.0版本已经发布,在狂热的JavaScript世界里带来了让人耳目一新的变化. Vue创建者尤雨溪称,Vue 2.0  ...

  5. 精通Web Analytics 2.0 (9) 第七章:失败更快:爆发测试与实验的能量

    精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第七章:失败更快:爆发测试与实验的能量 欢迎来到实验和测试这个棒极了的世界! 如果Web拥有一个超越所有其他渠道的巨大优势,它就 ...

  6. ubuntu 12.04 LTS 如何使用更快的更新源

    装好ubuntu系统后的第一见事就是替换自带的更新源,原因是系统自带的源有些在中国访问不了,可以访问的速度又特别慢.幸好国内的一些公司和大学提供了速度不错的更新源.下面介绍如何使用更快的更新源 方法/ ...

  7. CSS 和 JS 动画哪个更快

    基于Javascript的动画暗中同CSS过渡效果一样,甚至更加快,这怎么可能呢?而Adobe和Google持续发布的富媒体移动网站的性能可媲美本地应用,这又怎么可能呢? 本文逐一遍览了基于Javas ...

  8. CSS VS JS动画,哪个更快[译]

    英文原文:https://davidwalsh.name/css-js-animation 原作者Julian Shapiro是Velocity.js的作者,Velocity.js是一个高效易用的js ...

  9. 让DB2跑得更快——DB2内部解析与性能优化

    让DB2跑得更快——DB2内部解析与性能优化 (DB2数据库领域的精彩强音,DB2技巧精髓的热心分享,资深数据库专家牛新庄.干毅民.成孜论.唐志刚联袂推荐!)  洪烨著 2013年10月出版 定价:7 ...

随机推荐

  1. leetcode849

    public class Solution { public int MaxDistToClosest(int[] seats) { ; var len = seats.Length; ) { ; } ...

  2. From Ruby array to JS array in Rails- 'quote'?

    From Ruby array to JS array in Rails- 'quote'? <%= raw @location_list.as_json %>

  3. asp.net 编码 解码

    编码代码: System.Web.HttpUtility.HtmlEncode("<a href=\"http://hovertree.com/\">何问起& ...

  4. dart 命名规范

    1.类型 首字母大写 譬如 abstract class Shape 2.变量 驼峰式命名,首字母小写 class Article { String headUrl; String user; Str ...

  5. Echarts在java中使用

    index.jsp <%@ page language="java" import="java.util.*" pageEncoding="UT ...

  6. Apache Hive (七)Hive的DDL操作

    转自:https://www.cnblogs.com/qingyunzong/p/8723271.html 库操作 1.创建库 语法结构 CREATE (DATABASE|SCHEMA) [IF NO ...

  7. Composer切换到Laravel-China 镜像

    全局 composer config -g repo.packagist composer https://packagist.laravel-china.org 该项目 composer confi ...

  8. selenium+jenkins网页自动化测试的构建

    jenkins+selenium可以做到对web自动化的持续集成. Jenkins的基本操作: 一.新建视图及job 新建视图: 新建job: 可以选择构建一个自由风格的软件项目或者复制已有的item ...

  9. style多次设置行内样式

    语法 style="font-size:32px;background-color:#aaa"

  10. centos 6.5 部署openvpn 2.4

    软件下载地址 软件下载地址 https://openvpn.net/index.php/open-source/downloads.html 服务端 源Tarball(gzip) https://sw ...