欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-11-03 14:03:28
php实现大文件断点续传下载实例,看完你就知道超过100M以上的大文件如何断点传输了,这个功能还是比较经典实用的,毕竟大文件上传功能经常用得到。 ......

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

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

 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\n2000"; 
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\n380 
 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 }


本文转自: 转载请注明出处!