解决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中防止SQL注入实现代码
Feb 19 PHP
php中如何同时使用session和cookie来保存用户登录信息
Jul 05 PHP
PHP将回调函数作用到给定数组单元的方法
Aug 19 PHP
PHP基本语法总结
Sep 06 PHP
thinkPHP实现表单自动验证
Dec 24 PHP
php生成rss类用法实例
Apr 14 PHP
PHP文件生成的图片无法使用CDN缓存的解决方法
Jun 20 PHP
php redis实现对200w用户的即时推送
Mar 04 PHP
php实现的二叉树遍历算法示例
Jun 15 PHP
[原创]php token使用与验证示例【测试可用】
Aug 30 PHP
PHP的RSA加密解密方法以及开发接口使用
Feb 11 PHP
TP5框架请求响应参数实例分析
Oct 17 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 magic_quotes_gpc的一点认识与分析
2008/08/18 PHP
解析在apache里面给php写虚拟目录的详细方法
2013/06/24 PHP
php中用date函数获取当前时间有误的解决办法
2013/08/02 PHP
非常实用的PHP常用函数汇总
2014/12/17 PHP
详解WordPress中提醒安装插件以及隐藏插件的功能实现
2015/12/25 PHP
PHP弱类型的安全问题详细总结
2016/09/25 PHP
php连接微软MSSQL(sql server)完全攻略
2016/11/27 PHP
PHP 序列化和反序列化函数实例详解
2020/07/18 PHP
PHP convert_uudecode()函数讲解
2019/02/14 PHP
JavaScript使用prototype定义对象类型
2007/02/07 Javascript
javascript 不间断的图片滚动并可点击
2010/01/15 Javascript
struts2+jquery组合验证注册用户是否存在
2014/04/30 Javascript
JS中prototype的用法实例分析
2015/03/19 Javascript
使用CDN和AJAX加速WordPress中jQuery的加载
2015/12/05 Javascript
浅谈JS中的!=、== 、!==、===的用法和区别
2016/09/24 Javascript
百度地图JavascriptApi Marker平滑移动及车头指向行径方向
2017/03/13 Javascript
jQuery实现的form转json经典示例
2017/10/10 jQuery
vue实现商城上货组件简易版
2017/11/27 Javascript
Vue官网todoMVC示例代码
2018/01/29 Javascript
Babel 入门教程学习笔记
2018/06/13 Javascript
js实现按钮开关单机下拉菜单效果
2018/11/22 Javascript
Vue+Webpack完美整合富文本编辑器TinyMce的方法
2018/11/30 Javascript
JavaScript设计模式之装饰者模式实例详解
2019/01/17 Javascript
Nginx设置为Node.js的前端服务器方法总结
2019/03/27 Javascript
微信小程序swiper使用网络图片不显示问题解决
2019/12/13 Javascript
解决echarts中横坐标值显示不全(自动隐藏)问题
2020/07/20 Javascript
详解python里使用正则表达式的分组命名方式
2017/10/24 Python
Python实现的井字棋(Tic Tac Toe)游戏示例
2018/01/31 Python
pandas 取出表中一列数据所有的值并转换为array类型的方法
2018/04/11 Python
对Python 数组的切片操作详解
2018/07/02 Python
pandas 按照特定顺序输出的实现代码
2018/07/10 Python
DJANGO-URL反向解析REVERSE实例讲解
2019/10/25 Python
Python迭代器协议及for循环工作机制详解
2020/07/14 Python
Python将字典转换为XML的方法
2020/08/01 Python
Selenium执行完毕未关闭chromedriver/geckodriver进程的解决办法(java版+python版)
2020/12/07 Python
2015毕业生实习期工作总结
2015/04/09 职场文书