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 相关文章推荐
PHP 实现多服务器共享 SESSION 数据
Aug 15 PHP
php 数组的指针操作实现代码
Feb 08 PHP
php中使用cookie来保存用户登录信息的实现代码
Mar 08 PHP
解析php中var_dump,var_export,print_r三个函数的区别
Jun 21 PHP
php读取csv文件后,uft8 bom导致在页面上显示出现问题的解决方法
Aug 10 PHP
ThinkPHP3.1新特性之G方法的使用
Jun 19 PHP
php调用新浪短链接API的方法
Nov 08 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
Mar 19 PHP
php脚本运行时的超时机制详解
Feb 17 PHP
PHP的全局错误处理详解
Apr 25 PHP
PHP实现基于状态的责任链审批模式详解
May 31 PHP
解决laravel(5.5)访问public报错的问题
Oct 12 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
WHOIS类的修改版
2006/10/09 PHP
PHP 和 XML: 使用expat函数(三)
2006/10/09 PHP
php mysql索引问题
2008/06/07 PHP
[原创]效率较高的php下读取文本文件的代码
2008/07/02 PHP
PHP以及MYSQL日期比较方法
2012/11/29 PHP
php实现利用phpexcel导出数据
2013/08/24 PHP
四种php中webservice实现的简单架构方法及实例
2015/02/03 PHP
php用ini_get获取php.ini里变量值的方法
2015/03/04 PHP
php导入模块文件分享
2015/03/17 PHP
php中时间函数date及常用的时间计算
2017/05/12 PHP
Cookie跨域问题解决方案代码示例
2020/11/24 PHP
鼠标悬停小图标显示大图标
2016/01/22 Javascript
关于jQuery里prev()的简单操作代码
2017/10/27 jQuery
使用原生JS实现滚轮翻页效果的示例代码
2020/05/31 Javascript
[03:40]DOTA2亚洲邀请赛小组赛第二日 赛事回顾
2015/01/31 DOTA
[05:24]TI9采访——教练
2019/08/24 DOTA
详细探究Python中的字典容器
2015/04/14 Python
深入学习python的yield和generator
2016/03/10 Python
Python中super()函数简介及用法分享
2016/07/11 Python
Python for循环生成列表的实例
2018/06/15 Python
关于Keras模型可视化教程及关键问题的解决
2020/01/24 Python
Python编写单元测试代码实例
2020/09/10 Python
python使用Windows的wmic命令监控文件运行状况,如有异常发送邮件报警
2021/01/30 Python
彪马加拿大官网:PUMA加拿大
2018/10/04 全球购物
欧姆龙医疗保健与医疗产品:Omron Healthcare
2020/02/10 全球购物
类的核心特性有哪些
2014/01/01 面试题
业务员岗位职责范本
2013/12/15 职场文书
思想专业自荐信范文
2013/12/25 职场文书
工作室成员个人发展规划范文
2014/01/24 职场文书
班级文化建设标语
2014/06/23 职场文书
学校总务处领导班子民主生活会对照检查材料思想汇报
2014/09/27 职场文书
优秀班主任申报材料
2014/12/16 职场文书
python自动统计zabbix系统监控覆盖率的示例代码
2021/04/03 Python
解决Go gorm踩过的坑
2021/04/30 Golang
浅谈Python数学建模之固定费用问题
2021/06/23 Python
微信小程序APP页面的之间的相互传递参数以及自定义组件
2022/04/19 Javascript