一般来说, 我们可以通过直接让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. [转] C#中out和ref之间的区别

    gskcc 的原文地址 C#中out和ref之间的区别 首先:两者都是按地址传递的,使用后都将改变原来参数的数值. 其次:ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个 ...

  2. 「小程序JAVA实战」小程序页面引用外部wxml通用页面(21)

    转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-21/ 现在都是讲究开发的效率,原来单纯的android 和 ios 已经不在吃香了,都是混合开发, ...

  3. 阻塞IO,非阻塞IO,异步IO和非异步IO 的区别

    最近在研究java IO.NIO.NIO2(或者称AIO)相关的东西,有些概念还是要明确下. 按照<Unix网络编程>的划分,IO模型可以分为:阻塞IO.非阻塞IO.IO复用.信号驱动IO ...

  4. Android MVP模式简单易懂的介绍方式 (三)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 讲完M和P,接下来就要讲V了.View ...

  5. Python基础学习八 写日志

    import logging from logging import handlers class Logger(object): level_relations = { 'debug': loggi ...

  6. Bower 使用

    Bower:客户端库管理工具 来自<JavaScript 标准参考教程(alpha)>,by 阮一峰 目录 概述 常用操作 项目初始化 库的安装 库的搜索和查看 库的更新和卸载 列出所有库 ...

  7. 译文:TypeScript新手指南

    你是否听过 TypeScript? TypeScript 是微软开发的 JavaScript 的超集,TypeScript兼容JavaScript,可以载入JavaScript代码然后运行.TypeS ...

  8. Excel另存为_有些Excel打开时会出现一些提示

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  9. 【HDU3853】LOOPS

    题意 有一个R*C的方格.一个人想从(1,1)走到(r,c).在每个格子都有三种选择,向下,向右,或者原地不动.每个格子里的每个选择都有一定的概率.而每次移动都需要消耗2点的能量,问期望消耗的能量是多 ...

  10. ajax获取json数据为undefined--原因解析

    解决办法:var dataObj=eval("("+data+")");//转换为json对象 问题: 1. 碰到一个问题ajax成功获取json数据后,取值显 ...