当前位置:首页 > PHP教程 > php上传下载 > 列表

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

发布:smiling 来源: PHP粉丝网  添加日期:2021-12-26 16:25:20 浏览: 评论:0 

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

php大文件断点续传

  1. require_once('download.class.php');  
  2. date_default_timezone_set('Asia/Shanghai');  
  3. error_reporting(E_STRICT);  
  4. function errorHandler($errno$errstr$errfile$errline) {  
  5.  echo '<p>error:'$errstr'</p>';  
  6.  exit();  
  7. }  
  8. set_error_handler('errorHandler');  
  9. define('IS_DEBUG', true);  
  10. $filePath = 'test.zip';  
  11. $mimeType = 'audio/x-matroska';  
  12. $range = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : null;  
  13. if (IS_DEBUG) {  
  14. // $range = "bytes=1000-1999\n2000";  
  15. // $range = "bytes=1000-1999,2000";  
  16. // $range = "bytes=1000-1999,-2000";  
  17. // $range = "bytes=1000-1999,2000-2999";  
  18. }  
  19. set_time_limit(0);  
  20. $transfer = new Transfer($filePath$mimeType$range);  
  21. if (IS_DEBUG) {  
  22.  $transfer->setIsLog(true);  
  23. }  
  24. $transfer->send(); 
  25. require_once('download.class.php');  
  26. date_default_timezone_set('Asia/Shanghai');  
  27. error_reporting(E_STRICT);  
  28. function errorHandler($errno$errstr$errfile$errline) {  
  29.  echo '<p>error:'$errstr'</p>';  
  30.  exit();  
  31. }  
  32. set_error_handler('errorHandler');  
  33. define('IS_DEBUG', true);  
  34. $filePath = 'test.zip';  
  35. $mimeType = 'audio/x-matroska';  
  36. $range = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : null;  
  37. if (IS_DEBUG) {  
  38. // $range = "bytes=1000-1999\n2000";  
  39. // $range = "bytes=1000-1999,2000";  
  40. // $range = "bytes=1000-1999,-2000";  
  41. // $range = "bytes=1000-1999,2000-2999";  
  42. }  
  43. set_time_limit(0);  
  44. $transfer = new Transfer($filePath$mimeType$range);  
  45. if (IS_DEBUG) {  
  46.  $transfer->setIsLog(true);  
  47. }  
  48. $transfer->send(); 

download.class.php

  1. /**  
  2.  * 文件传输,支持断点续传。  
  3.  * 2g以上超大文件也有效  
  4.  * @author MoXie  
  5.  */ 
  6. class Transfer {  
  7.  /**  
  8.   * 缓冲单元  
  9.   */ 
  10.  const BUFF_SIZE = 5120; // 1024 * 5  
  11.  /**  
  12.   * 文件地址  
  13.   * @var <String>  
  14.   */ 
  15.  private $filePath;  
  16.  /**  
  17.   * 文件大小  
  18.   * @var <String> Php超大数字 字符串形式描述  
  19.   */ 
  20.  private $fileSize;  
  21.  /**  
  22.   * 文件类型  
  23.   * @var <String>  
  24.   */ 
  25.  private $mimeType;  
  26.  /**  
  27.   * 请求区域(范围)  
  28.   * @var <String>  
  29.   */ 
  30.  private $range;  
  31.  /**  
  32.   * 是否写入日志  
  33.   * @var <Boolean>  
  34.   */ 
  35.  private $isLog = false;  
  36.  /**  
  37.   *  
  38.   * @param <String> $filePath 文件路径  
  39.   * @param <String> $mimeType 文件类型  
  40.   * @param <String> $range 请求区域(范围)  
  41.   */ 
  42.  function __construct($filePath$mimeType = null, $range = null) {  
  43.   $this->filePath = $filePath;  
  44.   $this->fileSize = sprintf('%u'filesize($filePath));  
  45.   $this->mimeType = ($mimeType != null) ? $mimeType : "application/octet-stream"// bin  
  46.   $this->range = trim($range);  
  47.  }  
  48.  /**  
  49.   * 获取文件区域  
  50.   * @return <Map> {'start':long,'end':long} or null  
  51.   */ 
  52.  private function getRange() {  
  53.   /**  
  54.    * Range: bytes=-128  
  55.    * Range: bytes=-128  
  56.    * Range: bytes=28-175,382-399,510-541,644-744,977-980  
  57.    * Range: bytes=28-175\n380  
  58.    * type 1  
  59.    * RANGE: bytes=1000-9999  
  60.    * RANGE: bytes=2000-9999  
  61.    * type 2  
  62.    * RANGE: bytes=1000-1999  
  63.    * RANGE: bytes=2000-2999  
  64.    * RANGE: bytes=3000-3999  
  65.    */ 
  66.   if (!emptyempty($this->range)) {  
  67.    $range = preg_replace('/[\s|,].*/'''$this->range);  
  68.    $range = explode('-'substr($range, 6));  
  69.    if (count($range) < 2) {  
  70.     $range[1] = $this->fileSize// Range: bytes=-100  
  71.    }  
  72.    $range = array_combine(array('start''end'), $range);  
  73.    if (emptyempty($range['start'])) {  
  74.     $range['start'] = 0;  
  75.    }  
  76.    if (!isset($range['end']) || emptyempty($range['end'])) {  
  77.     $range['end'] = $this->fileSize;  
  78.    }  
  79.    return $range;  
  80.   }  
  81.   return null;  
  82.  }  
  83.  /**  
  84.   * 向客户端发送文件  
  85.   */ 
  86.  public function send() {  
  87.   $fileHande = fopen($this->filePath, 'rb');  
  88.   if ($fileHande) {  
  89.    // setting  
  90.    ob_end_clean(); // clean cache  
  91.    ob_start();  
  92.    ini_set('output_buffering''Off');  
  93.    ini_set('zlib.output_compression''Off');  
  94.    $magicQuotes = get_magic_quotes_gpc();  
  95. //   set_magic_quotes_runtime(0);  
  96.    // init  
  97.    $lastModified = gmdate('D, d M Y H:i:s'filemtime($this->filePath)) . ' GMT';  
  98.    $etag = sprintf('w/"%s:%s"', md5($lastModified), $this->fileSize);  
  99.    $ranges = $this->getRange();  
  100.    // headers  
  101.    header(sprintf('Last-Modified: %s'$lastModified));  
  102.    header(sprintf('ETag: %s'$etag));  
  103.    header(sprintf('Content-Type: %s'$this->mimeType));  
  104.    $disposition = 'attachment';  
  105.    if (strpos($this->mimeType, 'image/') !== FALSE) {  
  106.     $disposition = 'inline';  
  107.    }  
  108.    header(sprintf('Content-Disposition: %s; filename="%s"'$dispositionbasename($this->filePath)));  
  109.    if ($ranges != null) {  
  110.     if ($this->isLog) {  
  111.      $this->log(json_encode($ranges) . ' ' . $_SERVER['HTTP_RANGE']);  
  112.     }  
  113.     header('HTTP/1.1 206 Partial Content');  
  114.     header('Accept-Ranges: bytes');  
  115.     header(sprintf('Content-Length: %u'$ranges['end'] - $ranges['start']));  
  116.     header(sprintf('Content-Range: bytes %s-%s/%s'$ranges['start'], $ranges['end'], $this->fileSize));  
  117.     //  
  118.     fseek($fileHande, sprintf('%u'$ranges['start']));  
  119.    } else {  
  120.     header("HTTP/1.1 200 OK");  
  121.     header(sprintf('Content-Length: %s'$this->fileSize));  
  122.    }  
  123.    // read file  
  124.    $lastSize = 0;  
  125.    while (!feof($fileHande) && !connection_aborted()) {  
  126.     $lastSize = sprintf("%u", bcsub($this->fileSize, sprintf("%u"ftell($fileHande))));  
  127.     if (bccomp($lastSize, self::BUFF_SIZE) > 0) {  
  128.      $lastSize = self::BUFF_SIZE;  
  129.     }  
  130.     echo fread($fileHande$lastSize);  
  131.     ob_flush();  
  132.     flush();  
  133.    }  
  134.    set_magic_quotes_runtime($magicQuotes);  
  135.    ob_end_flush();  
  136.   }  
  137.   if ($fileHande != null) {  
  138.    fclose($fileHande);  
  139.   }  
  140.  }  
  141.  /**  
  142.   * 设置记录  
  143.   * @param <Boolean> $isLog 是否记录  
  144.   */ 
  145.  public function setIsLog($isLog = true) {  
  146.   $this->isLog = $isLog;  
  147.  }  
  148.  /**  
  149.   * 记录  
  150.   * @param <String> $msg 记录信息  
  151.   */ 
  152.  private function log($msg) {  
  153.   try {  
  154.    $handle = fopen('transfer_log.txt''a');  
  155.    fwrite($handle, sprintf('%s : %s' . PHP_EOL, date('Y-m-d H:i:s'), $msg));  
  156.    fclose($handle);  
  157.   } catch (Exception $e) {  
  158.    // null;  
  159.   }  
  160.  }  
  161. }

Tags: php大文件断点续传

分享到: