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


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

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

    download.class.php

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


    本文转自:https://www.sucaihuo.com/php/277.html 转载请注明出处!

  • 相关阅读:
    zabbix邮件报警功能的验证
    linux下拷贝命令中的文件过滤操作记录
    Docker容器数据卷-Volume小结
    Elasticsearch集群监控指标学习
    MySQL 更换MyISAM存储引擎为Innodb的操作记录
    MySQL 占用过高CPU时的优化手段
    MySQL 连接数设置操作(Too many connections)及设置md5值的加密密码
    Android Studio aidl文件路径自定义问题
    Android资源混淆 + 混淆忽略 .so库
    Android Studio 换主题(Material Theme..)
  • 原文地址:https://www.cnblogs.com/mrlime/p/11615025.html
Copyright © 2020-2023  润新知