php实现大文件断点续传下载实例代码
吾爱主题
阅读:198
2021-08-25 15:41:00
评论:0
php实现大文件断点续传下载实例,看完你就知道超过100M以上的大文件如何断点传输了,这个功能还是比较经典实用的,毕竟大文件上传功能经常用得到。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | /** * 文件传输,支持断点续传。 * 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实现大文件断点续传下载实例代码,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!
原文链接:https://www.cnblogs.com/mrlime/archive/2019/10/01/11615025.html
声明
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。