php提供更快的文件下载
在微博上偶然看到一篇介绍php更快下载文件的方法,其实就是利用web服务器的xsendfile特性,鸟哥的博客中只说了apache的实现方式,我找到了介绍nginx实现方式的文章,整理一下!
let's go!
一般来说, 我们可以通过直接让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.
nginx中也有对应的xsendfile模块,默认已经包含了senfile模块了,你如果安装完nginx你会在nginx.conf文件会看到“sendfile on;”
配置部分:
server {
listen 80;
server_name demo.markdream.com;
root /var/vhost/demo;
index index.php;
# 这个是定义读取你的文件的目录的url开头 直接访问是不可以的 只能通过
location /protected {
internal;
alias /var/vhost/demo/uploadfiles;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
}
downloads.php
<?php //eg: http://demo.markdream.com/xsendfile/downloads.php?filename=hello.docx // 获取文件名
$filename = $_GET["filename"]; // 你可以在这里写下你的查询数据库等你所想的功能 …… header ( "Content-type: application/octet-stream" );
// 处理中文文件名
$ua = $_SERVER ["HTTP_USER_AGENT"];
if (preg_match ( "/MSIE/", $ua )) {
$encoded_filename = rawurlencode ( $filename );
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 . '"' );
} // 就这么简单一句话搞定 注意“protected”是和nginx配置文件的 protected要一致
header("X-Accel-Redirect: /protected/" . $filename); ?>
这里是使用的别名的方式,也可以使用直接访问的方式,具体看nginx官网的关于xsendfile的说明,一看就懂了!
参考和摘抄:
1.鸟哥:http://www.laruence.com/2012/05/02/2613.html
2.nginx 实现:https://www.markdream.com/technologies/programs/nginx-x-accel- redirect-php-practise.shtml?utm_source=tuicool&utm_medium=referral
3.nginx xsendfile官网说明:http://wiki.nginx.org/XSendfile
php提供更快的文件下载的更多相关文章
- 如何为终端用提供更快的解决方案?让IT技术员具备更高的效率?
- SharePoint 2010中使用SPListItemCollectionPosition更快的结果
转:http://www.16kan.com/article/detail/318657.html Introduction介绍 In this article we will explore the ...
- 更快的Maven来了,我的天,速度提升了8倍!
周末被 maven-mvnd 刷屏了,于是我也下载了一个 mvnd 体验了一把.虽然测试的数据都是基于我本地项目,不具备普适性和权威性,但也足以说明问题.它的测试结果远远超出我的预期,下面一起来看. ...
- 更快的Maven构建工具mvnd和Gradle哪个更快?
Maven 作为经典的项目构建工具相信很多人已经用很久了,但如果体验过 Gradle,那感觉只有两个字"真香". 前段时间测评了更快的 Maven 构建工具 mvnd,感觉性能挺高 ...
- 海量数据分析更快、更稳、更准。GaussDB(for MySQL) HTAP只读分析特性详解
本文作者康祥,华为云数据库内核开发工程师,研究生阶段主要从事SPARQL查询优化相关工作.目前在华为公司参与华为云GaussDB(for MySQL) HTAP只读内核功能设计和研发. 1. 引言 H ...
- QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用
FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QL ...
- 更轻更快的Vue.js 2.0与其他框架对比(转)
更轻更快的Vue.js 2.0 崭露头角的JavaScript框架Vue.js 2.0版本已经发布,在狂热的JavaScript世界里带来了让人耳目一新的变化. Vue创建者尤雨溪称,Vue 2.0 ...
- 精通Web Analytics 2.0 (9) 第七章:失败更快:爆发测试与实验的能量
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第七章:失败更快:爆发测试与实验的能量 欢迎来到实验和测试这个棒极了的世界! 如果Web拥有一个超越所有其他渠道的巨大优势,它就 ...
- ubuntu 12.04 LTS 如何使用更快的更新源
装好ubuntu系统后的第一见事就是替换自带的更新源,原因是系统自带的源有些在中国访问不了,可以访问的速度又特别慢.幸好国内的一些公司和大学提供了速度不错的更新源.下面介绍如何使用更快的更新源 方法/ ...
随机推荐
- 一个完整的TCP连接
当我们向服务器发送HTTP请求,获取数据.修改信息时,都需要建立TCP连接,包括三次握手,四次分手. 什么是TCP连接? 为实现数据的可靠传输,TCP要在应用进程间建立传输连接.它是在两个传输用户之间 ...
- 第24章 java线程(3)-线程的生命周期
java线程(3)-线程的生命周期 1.两种生命周期流转图 ** 生命周期:**一个事物冲从出生的那一刻开始到最终死亡中间的过程 在事物的漫长的生命周期过程中,总会经历不同的状态(婴儿状态/青少年状态 ...
- java 移位运算符
java中有三种移位运算符 << : 左移运算符,num << 1,相当于num乘以2 >> : 右移运算符,num >& ...
- 微信小程序之触控事件(四)
[未经作者本人同意,请勿以任何形式转载] >>>什么是事件 事件是视图层到逻辑层的通讯方式. 事件可以将用户的行为反馈到逻辑层进行处理. 事件可以绑定在组件上,当达到触发事件,就会执 ...
- Writing Clean Code 读后感
最近花了一些时间看了这本书,书名是 <Writing Clean Code ── Microsoft Techniques for Developing Bug-free C Programs& ...
- 通过sqlserver发送邮件
配置过程请参考:http://www.2cto.com/database/201403/289114.html 实际中应用的扩展: 1.编写一个触发器(相当于一个多线程的发邮件的服务). 2.在应用程 ...
- Batsing的网页编程规范(HTML/CSS/JS/PHP)
特别注意!!!我这里的前端编程规范不苟同于Bootstrap的前端规范. 因为我和它的目的不同,Bootstrap规范是极简主义,甚至有些没有考虑到兼容性的问题. 我的规范是自己从编程实践中总结出来的 ...
- 淘宝WAP版小BUG分析
前几天发现的一个淘宝WAP版的小BUG,就是用桌面版chrome看的时候产品评价中的图片显示不出来,都是图裂了. 这是什么原因呢?图片为什么会显示不出来呢?淘宝的技术人员.测试人员不可能没发现啊.开启 ...
- Android BLE 蓝牙编程(二)
大家中秋快乐啊--哈哈,今天继续工程项目吧! 上篇我们已经实现了蓝牙设备的扫描,本篇我们来通过list展示扫描到的设备并 实现点击连接. 先贴出上篇的完整的MainActivity的方法: packa ...
- datatable刷新表头
使用jQuery的datatable生成表格数据,当需要改变表头时,调用Table.fnDestroy();再重新创建表头 var oTable = null; function initSettin ...