解决PHP超大文件下载,断点续传下载的方法详解


Posted in PHP onJune 06, 2013

最近导出的时候出现一个php内存溢出的问题,原因就是在于下载的时候读取生成的临时文件过大,PHP内存无法容纳,一开如是想到更改PHP内存限制,但是这个只是一个缓兵之计,于是想到了另外一个方法是把文件分次读取,并下载。
以下是源代码:

<?php 
$sourceFile = "1.tmp"; //要下载的临时文件名 
$outFile = "用户订单.xls"; //下载保存到客户端的文件名 
$file_extension = strtolower(substr(strrchr($sourceFile, "."), 1)); //获取文件扩展名 
//echo $sourceFile; 
if (!ereg("[tmp|txt|rar|pdf|doc]", $file_extension))exit ("非法资源下载"); 
//检测文件是否存在 
if (!is_file($sourceFile)) { 
die("<b>404 File not found!</b>"); 
} 
$len = filesize($sourceFile); //获取文件大小 
$filename = basename($sourceFile); //获取文件名字 
$outFile_extension = strtolower(substr(strrchr($outFile, "."), 1)); //获取文件扩展名 
//根据扩展名 指出输出浏览器格式 
switch ($outFile_extension) { 
case "exe" : 
$ctype = "application/octet-stream"; 
break; 
case "zip" : 
$ctype = "application/zip"; 
break; 
case "mp3" : 
$ctype = "audio/mpeg"; 
break; 
case "mpg" : 
$ctype = "video/mpeg"; 
break; 
case "avi" : 
$ctype = "video/x-msvideo"; 
break; 
default : 
$ctype = "application/force-download"; 
} 
//Begin writing headers 
header("Cache-Control:"); 
header("Cache-Control: public"); 
//设置输出浏览器格式 
header("Content-Type: $ctype"); 
header("Content-Disposition: attachment; filename=" . $outFile); 
header("Accept-Ranges: bytes"); 
$size = filesize($sourceFile); 
//如果有$_SERVER['HTTP_RANGE']参数 
if (isset ($_SERVER['HTTP_RANGE'])) { 
/*Range头域 Range头域可以请求实体的一个或者多个子范围。 
例如, 
表示头500个字节:bytes=0-499 
表示第二个500字节:bytes=500-999 
表示最后500个字节:bytes=-500 
表示500字节以后的范围:bytes=500- 
第一个和最后一个字节:bytes=0-0,-1 
同时指定几个范围:bytes=500-600,601-999 
但是服务器可以忽略此请求头,如果无条件GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是以200 (OK)。 
*/ 
// 断点后再次连接 $_SERVER['HTTP_RANGE'] 的值 bytes=4390912- 
list ($a, $range) = explode("=", $_SERVER['HTTP_RANGE']); 
//if yes, download missing part 
str_replace($range, "-", $range); //这句干什么的呢。。。。 
$size2 = $size -1; //文件总字节数 
$new_length = $size2 - $range; //获取下次下载的长度 
header("HTTP/1.1 206 Partial Content"); 
header("Content-Length: $new_length"); //输入总长 
header("Content-Range: bytes $range$size2/$size"); //Content-Range: bytes 4908618-4988927/4988928 95%的时候 
} else { 
//第一次连接 
$size2 = $size -1; 
header("Content-Range: bytes 0-$size2/$size"); //Content-Range: bytes 0-4988927/4988928 
header("Content-Length: " . $size); //输出总长 
} 
//打开文件 
$fp = fopen("$sourceFile", "rb"); 
//设置指针位置 
fseek($fp, $range); 
//虚幻输出 
while (!feof($fp)) { 
//设置文件最长执行时间 
set_time_limit(0); 
print (fread($fp, 1024 * 8)); //输出文件 
flush(); //输出缓冲 
ob_flush(); 
} 
fclose($fp); 
exit ();

PHP 相关文章推荐
php颜色转换函数hex-rgb(将十六进制格式转成十进制格式)
Sep 23 PHP
PHP程序员基本要求和必备技能
May 09 PHP
PHP中使用json数据格式定义字面量对象的方法
Aug 20 PHP
php有道翻译api调用方法实例
Dec 22 PHP
php实现refresh刷新页面批量导入数据的方法
Dec 23 PHP
php获取文件名后缀常用方法小结
Feb 24 PHP
PHP、Java des加密解密实例
Apr 27 PHP
PHP7.0版本备注
Jul 23 PHP
PHP中SSO Cookie登录分析和实现
Nov 06 PHP
PHP扩展Memcache分布式部署方案
Dec 06 PHP
php数组冒泡排序算法实例
May 06 PHP
php递归函数怎么用才有效
Feb 24 PHP
探讨PHP函数ip2long转换IP时数值太大产生负数的解决方法
Jun 06 #PHP
php IP转换整形(ip2long)的详解
Jun 06 #PHP
php全局变量和类配合使用深刻理解
Jun 05 #PHP
php数组声明、遍历、数组全局变量使用小结
Jun 05 #PHP
PHP Global变量定义当前页面的全局变量实现探讨
Jun 05 #PHP
PHP 常用数组内部函数(Array Functions)介绍
Jun 05 #PHP
php将gd生成的图片缓存到memcache的小例子
Jun 05 #PHP
You might like
用PHP+MySql编写聊天室
2006/10/09 PHP
php 数组的合并、拆分、区别取值函数集
2010/02/15 PHP
使用PHP如何实现高效安全的ftp服务器(一)
2015/12/20 PHP
PHP如何使用Memcached
2016/04/05 PHP
jQuery 1.7.2中getAll方法的疑惑分析
2012/05/23 Javascript
Jquery利用mouseenter和mouseleave实现鼠标经过弹出层且可以点击
2014/02/12 Javascript
通过url查找a元素应用案例
2014/04/29 Javascript
node.js超时timeout详解
2014/11/26 Javascript
jquery实现鼠标滑过显示提示框的方法
2015/02/05 Javascript
JavaScript实现的简单幂函数实例
2015/04/17 Javascript
总结在前端排序中遇到的问题
2016/07/19 Javascript
JS获取和修改元素样式的实例代码
2016/08/06 Javascript
详解Jquery Easyui的验证扩展
2017/01/09 Javascript
NodeJs测试框架Mocha的安装与使用
2017/03/28 NodeJs
jQuery实现Select下拉列表进行状态选择功能
2017/03/30 jQuery
JavaScript编写的网页小游戏,很给力
2017/08/18 Javascript
记一次vue-webpack项目优化实践详解
2019/02/17 Javascript
在Vue项目中使用snapshot测试的具体使用
2019/04/16 Javascript
微信小程序登陆注册功能的实现代码
2019/12/10 Javascript
Vue页面跳转传递参数及接收方式
2020/09/09 Javascript
仿照Element-ui实现一个简易的$message方法
2020/09/14 Javascript
vue中利用three.js实现全景图的完整示例
2020/12/07 Vue.js
vuex的使用和简易实现
2021/01/07 Vue.js
Python socket非阻塞模块应用示例
2019/09/12 Python
scrapy结合selenium解析动态页面的实现
2020/09/28 Python
Python中的面向接口编程示例详解
2021/01/17 Python
美国椅子和沙发制造商:La-Z-Boy
2020/10/25 全球购物
大学新生军训个人的自我评价
2013/10/03 职场文书
求职简历自荐信
2013/10/20 职场文书
关于打架的检讨书
2014/01/17 职场文书
幼儿园学前班幼儿评语
2014/12/29 职场文书
房地产销售经理岗位职责
2015/02/02 职场文书
教师求职自荐信范文
2015/03/04 职场文书
2015年度销售个人工作总结
2015/03/31 职场文书
2015年司法局工作总结
2015/05/22 职场文书
javascript之Object.assign()的痛点分析
2022/03/03 Javascript