php实现大文件断点续传下载实例代码


Posted in PHP onOctober 01, 2019

php实现大文件断点续传下载实例,看完你就知道超过100M以上的大文件如何断点传输了,这个功能还是比较经典实用的,毕竟大文件上传功能经常用得到。

php实现大文件断点续传下载实例代码

require_once('download.class.php'); 
date_default_timezone_set('Asia/Shanghai'); 
error_reporting(E_STRICT); 
function errorHandler($errno, $errstr, $errfile, $errline) { 
 echo '<p>error:', $errstr, '</p>'; 
 exit(); 
} 
set_error_handler('errorHandler'); 
define('IS_DEBUG', true); 
$filePath = 'test.zip'; 
$mimeType = 'audio/x-matroska'; 
$range = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : null; 
if (IS_DEBUG) { 
// $range = "bytes=1000-1999\n2000"; 
// $range = "bytes=1000-1999,2000"; 
// $range = "bytes=1000-1999,-2000"; 
// $range = "bytes=1000-1999,2000-2999"; 
} 
set_time_limit(0); 
$transfer = new Transfer($filePath, $mimeType, $range); 
if (IS_DEBUG) { 
 $transfer->setIsLog(true); 
} 
$transfer->send();

download.class.php

/** 
 * 文件传输,支持断点续传。 
 * 2g以上超大文件也有效 
 * @author MoXie 
 */ 
class Transfer { 
 /** 
  * 缓冲单元 
  */ 
 const BUFF_SIZE = 5120; // 1024 * 5 
 /** 
  * 文件地址 
  * @var <String> 
  */ 
 private $filePath; 
 /** 
  * 文件大小 
  * @var <String> Php超大数字 字符串形式描述 
  */ 
 private $fileSize; 
 /** 
  * 文件类型 
  * @var <String> 
  */ 
 private $mimeType; 
 /** 
  * 请求区域(范围) 
  * @var <String> 
  */ 
 private $range; 
 /** 
  * 是否写入日志 
  * @var <Boolean> 
  */ 
 private $isLog = false; 
 /** 
  * 
  * @param <String> $filePath 文件路径 
  * @param <String> $mimeType 文件类型 
  * @param <String> $range 请求区域(范围) 
  */ 
 function __construct($filePath, $mimeType = null, $range = null) { 
  $this->filePath = $filePath; 
  $this->fileSize = sprintf('%u', filesize($filePath)); 
  $this->mimeType = ($mimeType != null) ? $mimeType : "application/octet-stream"; // bin 
  $this->range = trim($range); 
 } 
 /** 
  * 获取文件区域 
  * @return <Map> {'start':long,'end':long} or null 
  */ 
 private function getRange() { 
  /** 
   * Range: bytes=-128 
   * Range: bytes=-128 
   * Range: bytes=28-175,382-399,510-541,644-744,977-980 
   * Range: bytes=28-175\n380 
   * type 1 
   * RANGE: bytes=1000-9999 
   * RANGE: bytes=2000-9999 
   * type 2 
   * RANGE: bytes=1000-1999 
   * RANGE: bytes=2000-2999 
   * RANGE: bytes=3000-3999 
   */ 
  if (!empty($this->range)) { 
   $range = preg_replace('/[\s|,].*/', '', $this->range); 
   $range = explode('-', substr($range, 6)); 
   if (count($range) < 2) { 
    $range[1] = $this->fileSize; // Range: bytes=-100 
   } 
   $range = array_combine(array('start', 'end'), $range); 
   if (empty($range['start'])) { 
    $range['start'] = 0; 
   } 
   if (!isset($range['end']) || empty($range['end'])) { 
    $range['end'] = $this->fileSize; 
   } 
   return $range; 
  } 
  return null; 
 } 
 /** 
  * 向客户端发送文件 
  */ 
 public function send() { 
  $fileHande = fopen($this->filePath, 'rb'); 
  if ($fileHande) { 
   // setting 
   ob_end_clean(); // clean cache 
   ob_start(); 
   ini_set('output_buffering', 'Off'); 
   ini_set('zlib.output_compression', 'Off'); 
   $magicQuotes = get_magic_quotes_gpc(); 
//   set_magic_quotes_runtime(0); 
   // init 
   $lastModified = gmdate('D, d M Y H:i:s', filemtime($this->filePath)) . ' GMT'; 
   $etag = sprintf('w/"%s:%s"', md5($lastModified), $this->fileSize); 
   $ranges = $this->getRange(); 
   // headers 
   header(sprintf('Last-Modified: %s', $lastModified)); 
   header(sprintf('ETag: %s', $etag)); 
   header(sprintf('Content-Type: %s', $this->mimeType)); 
   $disposition = 'attachment'; 
   if (strpos($this->mimeType, 'image/') !== FALSE) { 
    $disposition = 'inline'; 
   } 
   header(sprintf('Content-Disposition: %s; filename="%s"', $disposition, basename($this->filePath))); 
   if ($ranges != null) { 
    if ($this->isLog) { 
     $this->log(json_encode($ranges) . ' ' . $_SERVER['HTTP_RANGE']); 
    } 
    header('HTTP/1.1 206 Partial Content'); 
    header('Accept-Ranges: bytes'); 
    header(sprintf('Content-Length: %u', $ranges['end'] - $ranges['start'])); 
    header(sprintf('Content-Range: bytes %s-%s/%s', $ranges['start'], $ranges['end'], $this->fileSize)); 
    // 
    fseek($fileHande, sprintf('%u', $ranges['start'])); 
   } else { 
    header("HTTP/1.1 200 OK"); 
    header(sprintf('Content-Length: %s', $this->fileSize)); 
   } 
   // read file 
   $lastSize = 0; 
   while (!feof($fileHande) && !connection_aborted()) { 
    $lastSize = sprintf("%u", bcsub($this->fileSize, sprintf("%u", ftell($fileHande)))); 
    if (bccomp($lastSize, self::BUFF_SIZE) > 0) { 
     $lastSize = self::BUFF_SIZE; 
    } 
    echo fread($fileHande, $lastSize); 
    ob_flush(); 
    flush(); 
   } 
   set_magic_quotes_runtime($magicQuotes); 
   ob_end_flush(); 
  } 
  if ($fileHande != null) { 
   fclose($fileHande); 
  } 
 } 
 /** 
  * 设置记录 
  * @param <Boolean> $isLog 是否记录 
  */ 
 public function setIsLog($isLog = true) { 
  $this->isLog = $isLog; 
 } 
 /** 
  * 记录 
  * @param <String> $msg 记录信息 
  */ 
 private function log($msg) { 
  try { 
   $handle = fopen('transfer_log.txt', 'a'); 
   fwrite($handle, sprintf('%s : %s' . PHP_EOL, date('Y-m-d H:i:s'), $msg)); 
   fclose($handle); 
  } catch (Exception $e) { 
   // null; 
  } 
 } 
}

总结

以上所述是小编给大家介绍的php实现大文件断点续传下载实例代码,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

PHP 相关文章推荐
通过文字传递创建的图形按钮
Oct 09 PHP
PHP Mysql编程之高级技巧
Aug 27 PHP
解析php二分法查找数组是否包含某一元素
May 23 PHP
在PHP中运行Linux命令并启动SSH服务的例子
Jun 12 PHP
ThinkPHP多表联合查询的常用方法
Mar 24 PHP
PHP实现图片压缩的两则实例
Jul 19 PHP
PHP7.0安装笔记整理
Aug 28 PHP
利用PHP生成静态html页面的原理
Sep 30 PHP
php中上传文件的的解决方案
Sep 25 PHP
ThinkPHP5.0框架使用build 自动生成模块操作示例
Apr 11 PHP
thinkphp5.1框架中容器(Container)和门面(Facade)的实现方法分析
Aug 05 PHP
PHP实现考试倒计时功能代码
Apr 16 PHP
使用composer安装使用thinkphp6.0框架问题【视频教程】
Oct 01 #PHP
基于Laravel-admin 后台的自定义页面用法详解
Sep 30 #PHP
Laravel-admin之修改操作日志的方法
Sep 30 #PHP
laravel 字段格式化 modle 字段类型转换方法
Sep 30 #PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
Sep 30 #PHP
laravel-admin的图片删除实例
Sep 30 #PHP
laravel-admin的多级联动方法
Sep 30 #PHP
You might like
用PHP读取RSS feed的代码
2008/08/01 PHP
php调用mysql数据 dbclass类
2011/05/07 PHP
php mb_substr()函数截取中文字符串应用示例
2014/07/29 PHP
Yii学习总结之安装配置
2015/02/22 PHP
php session的锁和并发
2016/01/22 PHP
jquery 单击li防止重复加载的实现代码
2010/12/24 Javascript
基于jQuery的模仿新浪微博时间的组件
2011/10/04 Javascript
深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP
2012/01/15 Javascript
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
jquery ajax post提交数据乱码
2013/11/05 Javascript
使用jquery自定义鼠标样式满足个性需求
2013/11/05 Javascript
javascript日期对象格式化为字符串的实现方法
2014/01/14 Javascript
原生javascript实现简单的datagrid数据表格
2015/01/02 Javascript
JavaScript判断浏览器类型的方法
2015/02/10 Javascript
javascript实现相同事件名称,不同命名空间的调用方法
2015/06/26 Javascript
使用JavaScript脚本判断页面是否在微信中被打开
2016/03/06 Javascript
iframe中使用jquery进行查找的方法【案例分析】
2016/06/17 Javascript
在Angular中使用JWT认证方法示例
2018/09/10 Javascript
node+express框架中连接使用mysql(经验总结)
2018/11/10 Javascript
JavaScript字符串转数字的简单实现方法
2020/11/27 Javascript
[50:34]VGJ.T vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[00:38]TI珍贵瞬间系列(二):笑
2020/08/26 DOTA
Python实用技巧之列表、字典、集合中根据条件筛选数据详解
2018/07/11 Python
Python读取stdin方法实例
2019/05/24 Python
python线程的几种创建方式详解
2019/08/29 Python
python hash每次调用结果不同的原因
2019/11/21 Python
python如何变换环境
2020/07/21 Python
python利用xpath爬取网上数据并存储到django模型中
2021/02/26 Python
html5各种页面切换效果和模态对话框用法总结
2014/12/15 HTML / CSS
美国一家全面的在线零售鞋类公司:SHOEBACCA
2017/01/06 全球购物
EQVVS官网:设计师男装和女装
2018/10/24 全球购物
荷兰最大的鞋子、服装和运动折扣店:Bristol
2021/01/07 全球购物
关于打架的检讨书
2014/01/17 职场文书
签约仪式策划方案
2014/06/02 职场文书
党员检讨书
2014/10/13 职场文书
在python中读取和写入CSV文件详情
2022/06/28 Python