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中常用数组处理方法实例分析
Aug 30 PHP
PHP的一个基础知识 表单提交
Jul 04 PHP
深入array multisort排序原理的详解
Jun 18 PHP
关于使用key/value数据库redis和TTSERVER的心得体会
Jun 28 PHP
php实现查询百度google收录情况(示例代码)
Aug 02 PHP
单点登录 Ucenter示例分析
Oct 29 PHP
PHP中if和or运行效率对比
Dec 12 PHP
使用新浪微博API的OAuth认证发布微博实例
Mar 27 PHP
PHP实现事件机制的方法
Jul 10 PHP
PHP对象链式操作实现原理分析
Oct 09 PHP
利用laravel搭建一个迷你博客实战教程
Aug 13 PHP
PHP+mysql防止SQL注入的方法小结
Apr 27 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
第十五节--Zend引擎的发展
2006/11/16 PHP
phpadmin如何导入导出大数据文件及php.ini参数修改
2013/02/18 PHP
php数组查找函数in_array()、array_search()、array_key_exists()使用实例
2014/04/29 PHP
laravel清除视图缓存的代码
2019/10/23 PHP
Javascript 代码也可以变得优美的实现方法
2009/06/22 Javascript
jQuery UI AutoComplete 使用说明
2011/06/20 Javascript
THREE.JS入门教程(4)创建粒子系统
2013/01/24 Javascript
改变隐藏的input中value值的方法
2014/03/19 Javascript
javascript常用代码段搜集
2014/12/04 Javascript
JavaScript实现三阶幻方算法谜题解答
2014/12/29 Javascript
JavaScript随机打乱数组顺序之随机洗牌算法
2016/08/02 Javascript
js设置和获取自定义属性的方法
2016/10/20 Javascript
深入理解ES6学习笔记之块级作用域绑定
2017/08/19 Javascript
Windows下Node.js安装及环境配置方法
2017/09/18 Javascript
JS函数节流和函数防抖问题分析
2017/12/18 Javascript
手写简单的jQuery雪花飘落效果实例
2018/04/22 jQuery
JS异步错误捕获的一些事小结
2019/04/26 Javascript
vue-cli3+ts+webpack实现多入口多出口功能
2019/05/30 Javascript
js实现图片区域可点击大小随意改变(适用移动端)代码实例
2019/09/11 Javascript
layui之数据表格--与后台交互获取数据的方法
2019/09/29 Javascript
Flask框架学习笔记(一)安装篇(windows安装与centos安装)
2014/06/25 Python
浅谈python str.format与制表符\t关于中文对齐的细节问题
2019/01/14 Python
Python使用post及get方式提交数据的实例
2019/01/24 Python
python自定义函数def的应用详解
2020/06/03 Python
python实现图像高斯金字塔的示例代码
2020/12/11 Python
东方红海科技面试题软件测试方面
2012/02/08 面试题
联欢晚会主持词
2014/03/25 职场文书
上诉答辩状范文
2015/05/22 职场文书
有关浪费资源的建议书
2015/09/14 职场文书
送给自己的励志语句:要安静的优秀,悄无声息的坚强
2019/11/26 职场文书
500字作文之难忘的同学
2019/12/20 职场文书
晶体管来复再生式二管收音机
2021/04/22 无线电
分析设计模式之模板方法Java实现
2021/06/23 Java/Android
SQLServer中JSON文档型数据的查询问题解决
2021/06/27 SQL Server
「SHOW BY ROCK!!」“雫シークレットマインド”组合单曲MV公开
2022/03/21 日漫
Python3使用Qt5来实现简易的五子棋小游戏
2022/05/02 Python