002 /**
003 * 文件传输,支持断点续传。
004 * 2g以上超大文件也有效
005 * @author MoXie
006 */
007 class Transfer {
008 /**
009 * 缓冲单元
010 */
011 const BUFF_SIZE = 5120; // 1024 * 5
012 /**
013 * 文件地址
014 * @var
015 */
016 private $filePath;
017 /**
018 * 文件大小
019 * @var
020 */
021 private $fileSize;
022 /**
023 * 文件类型
024 * @var
025 */
026 private $mimeType;
027 /**
028 * 请求区域(范围)
029 * @var
030 */
031 private $range;
032 /**
033 * 是否写入日志
034 * @var
035 */
036 private $isLog = false;
037 /**
038 *
039 * @param
040 * @param
041 * @param
042 */
043 function __construct($filePath, $mimeType = null , $range = null) {
044 $this->filePath = $filePath;
045 $this->fileSize = sprintf('%u',filesize($filePath));
046 $this->mimeType = ($mimeType != null)?$mimeType:"application/octet-stream"; // bin
047 $this->range = trim($range);
048 }
049 /**
050 * 获取文件区域
051 * @return
052 */
053 private function getRange() {
054 /**
055 * Range: bytes=-128
056 * Range: bytes=-128
057 * Range: bytes=28-175,382-399,510-541,644-744,977-980
058 * Range: bytes=28-175n380
059 * type 1
060 * RANGE: bytes=1000-9999
061 * RANGE: bytes=2000-9999
062 * type 2
063 * RANGE: bytes=1000-1999
064 * RANGE: bytes=2000-2999
065 * RANGE: bytes=3000-3999
066 */
067 if (!empty($this->range)) {
068 $range = preg_replace('/[s|,].*/','',$this->range);
069 $range = explode('-',substr($range,6));
070 if (count($range)
071 $range[1] = $this->fileSize; // Range: bytes=-100
072 }
073 $range = array_combine(array('start','end'),$range);
074 if (empty($range['start'])) {
075 $range['start'] = 0;
076 }
077 if (!isset ($range['end']) || empty($range['end'])) {
078 $range['end'] = $this->fileSize;
079 }
080 return $range;
081 }
082 return null;
083 }
084 /**
085 * 向客户端发送文件
086 */
087 public function send() {
088 $fileHande = fopen($this->filePath, 'rb');
089 if ($fileHande) {
090 // setting
091 ob_end_clean();// clean cache
092 ob_start();
093 ini_set('output_buffering', 'Off');
094 ini_set('zlib.output_compression', 'Off');
095 $magicQuotes = get_magic_quotes_gpc();
096 set_magic_quotes_runtime(0);
097 // init
098 $lastModified = gmdate('D, d M Y H:i:s', filemtime($this->filePath)).' GMT';
099 $etag = sprintf('w/"%s:%s"',md5($lastModified),$this->fileSize);
100 $ranges = $this->getRange();
101 // headers
102 header(sprintf('Last-Modified: %s',$lastModified));
103 header(sprintf('ETag: %s',$etag));
104 header(sprintf('Content-Type: %s',$this->mimeType));
105 $disposition = 'attachment';
106 if (strpos($this->mimeType,'image/') !== FALSE) {
107 $disposition = 'inline';
108 }
109 header(sprintf('Content-Disposition: %s; filename="%s"',$disposition,basename($this->filePath)));
110
111 if ($ranges != null) {
112 if ($this->isLog) {
113 $this->log(json_encode($ranges).' '.$_SERVER['HTTP_RANGE']);
114 }
115 header('HTTP/1.1 206 Partial Content');
116 header('Accept-Ranges: bytes');
117 header(sprintf('Content-Length: %u',$ranges['end'] - $ranges['start']));
118 header(sprintf('Content-Range: bytes %s-%s/%s', $ranges['start'], $ranges['end'],$this->fileSize));
119 //
120 fseek($fileHande, sprintf('%u',$ranges['start']));
121 }else {
122 header("HTTP/1.1 200 OK");
123 header(sprintf('Content-Length: %s',$this->fileSize));
124 }
125 // read file
126 $lastSize = 0;
127 while(!feof($fileHande) && !connection_aborted()) {
128 $lastSize = sprintf("%u", bcsub($this->fileSize,sprintf("%u",ftell($fileHande))));
129 if (bccomp($lastSize,self::BUFF_SIZE) > 0) {
130 $lastSize = self::BUFF_SIZE;
131 }
132 echo fread($fileHande, $lastSize);
133 flush();
134 ob_flush();
135 }
136 set_magic_quotes_runtime($magicQuotes);
137 ob_end_flush();
138 }
139 if ($fileHande != null) {
140 fclose($fileHande);
141 }
142 }
143 /**
144 * 设置记录
145 * @param
146 */
147 public function setIsLog($isLog = true) {
148 $this->isLog = $isLog;
149 }
150 /**
151 * 记录
152 * @param
153 */
154 private function log($msg) {
155 try {
156 $handle = fopen('transfer_log.txt', 'a');
157 fwrite($handle, sprintf('%s : %s'.PHP_EOL,date('Y-m-d H:i:s'),$msg));
158 fclose($handle);
159 }catch(Exception $e) {
160 // null;
161 }
162 }
163 }
164 date_default_timezone_set('Asia/Shanghai');
165 error_reporting(E_STRICT);
166 function errorHandler($errno, $errstr, $errfile, $errline) {
167 echo '
error:',$errstr,'
';168 exit();
169 }
170 set_error_handler('errorHandler');
171 define('IS_DEBUG',true);
172
173 //
174 //
175 $filePath = '/Movie/The.Hurt.Locker.2008.x264.AC3-WAF.mkv';
176 $mimeType = 'audio/x-matroska';
177 $range = isset($_SERVER['HTTP_RANGE'])?$_SERVER['HTTP_RANGE']:null;
178 if (IS_DEBUG) {
179 // $range = "bytes=1000-1999n2000";
180 // $range = "bytes=1000-1999,2000";
181 // $range = "bytes=1000-1999,-2000";
182 // $range = "bytes=1000-1999,2000-2999";
183 }
184 set_time_limit(0);
185 $transfer = new Transfer($filePath,$mimeType,$range);
186 if (IS_DEBUG) {
187 $transfer->setIsLog(true);
188 }
189 $transfer->send();
190 ?>

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

SecList
SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

SublimeText3 Linux 새 버전
SublimeText3 Linux 최신 버전

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는
