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类
Nov 25 PHP
IIS6的PHP最佳配置方法
Mar 19 PHP
执行、获取远程代码返回:file_get_contents 超时处理的问题详解
Jun 25 PHP
PHP判断数据库中的记录是否存在的方法
Nov 14 PHP
php使用APC实现实时上传进度条功能
Oct 26 PHP
PHP类的声明与实例化及构造方法与析构方法详解
Jan 26 PHP
PHP上传图片类显示缩略图功能
Jun 30 PHP
php使用正则表达式去掉html中的注释方法
Nov 03 PHP
php实现等比例不失真缩放上传图片的方法
Nov 14 PHP
IOS 开发之NSDictionary转换成JSON字符串
Aug 14 PHP
基于php数组中的索引数组和关联数组详解
Mar 12 PHP
如何在PHP中生成随机数
Jun 04 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下几个常用的去空、分组、调试数组函数
2009/02/22 PHP
php知道与问问的采集插件代码
2010/10/12 PHP
浅谈php优化需要注意的地方
2014/11/27 PHP
PHP类的封装与继承详解
2015/09/29 PHP
thinkphp3.x连接mysql数据库的方法(具体操作步骤)
2016/05/19 PHP
Yii2实现log输出到file及database的方法
2016/11/12 PHP
PHP压缩图片功能的介绍
2019/03/21 PHP
PHP实现的62进制转10进制,10进制转62进制函数示例
2019/06/06 PHP
基于jQuery倾斜打开侧边栏菜单特效代码
2015/09/15 Javascript
详解JavaScript基于面向对象之创建对象(1)
2015/12/10 Javascript
原生javascript实现解析XML文档与字符串
2016/03/01 Javascript
vue.js 表格分页ajax 异步加载数据
2016/10/18 Javascript
Bootstrap CSS组件之面包屑导航(breadcrumb)
2016/12/17 Javascript
Angular限制input框输入金额(是小数的话只保留两位小数点)
2017/07/13 Javascript
Three.js 再探 - 写一个微信跳一跳极简版游戏
2018/01/04 Javascript
JS实现普通轮播图特效
2020/01/01 Javascript
使用Vue Composition API写出清晰、可扩展的表单实现
2020/06/10 Javascript
Python装饰器基础详解
2016/03/09 Python
Python 仅获取响应头, 不获取实体的实例
2019/08/21 Python
FFrpc python客户端lib使用解析
2019/08/24 Python
Python实现中值滤波去噪方式
2019/12/18 Python
Python基于Socket实现简单聊天室
2020/02/17 Python
python3.7调试的实例方法
2020/07/21 Python
详解Django自定义图片和文件上传路径(upload_to)的2种方式
2020/12/01 Python
纯CSS实现右侧底部悬浮效果(悬浮QQ、微信、微博、邮箱等联系方式)
2015/04/24 HTML / CSS
英国香水店:The Perfume Shop
2017/03/27 全球购物
生物化学研究助理员求职信
2013/10/09 职场文书
获奖的大学生创业计划书
2014/01/05 职场文书
打架检讨书2000字
2014/02/22 职场文书
餐厅总厨求职信
2014/03/04 职场文书
学术诚信承诺书
2014/05/26 职场文书
学校学雷锋活动总结
2014/06/26 职场文书
2014年学校党建工作总结
2014/11/11 职场文书
嘉宾邀请函
2015/01/31 职场文书
团委副书记工作总结
2015/08/14 职场文书
导游词之无锡东林书院
2019/12/11 职场文书