PHP로 대용량 파일 업로드를 재개하는 방법은 무엇입니까?

Guanhui
풀어 주다: 2023-04-09 06:00:02
앞으로
2569명이 탐색했습니다.

PHP로 대용량 파일 업로드를 재개하는 방법은 무엇입니까?

1. 이력서 다운로드 원칙

이력서 다운로드란 파일을 다운로드한 시점부터 계속해서 다운로드하는 것을 의미합니다. 이전 버전의 HTTP 프로토콜에서는 중단점이 지원되지 않았지만 HTTP/1.1부터 지원되었습니다. 일반적으로 Range 및 Content-Range 엔터티 헤더는 중단점 다운로드에만 사용됩니다.

중단점 재개를 사용하지 마세요

get /down.zip http/1.1<br/>accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-<br/>excel, application/msword, application/vnd.ms-powerpoint, */*<br/>accept-language: zh-cn<br/>accept-encoding: gzip, deflate<br/>user-agent: mozilla/4.0 (compatible; msie 5.01; windows nt 5.0)<br/>connection: keep-alive<br/>
로그인 후 복사

서버는 요청을 받은 후 필요에 따라 요청한 파일을 검색하고 파일 정보를 추출한 후 브라우저에 반환합니다.

HTTP/1.1 200 Ok<br/>content-length=106786028<br/>accept-ranges=bytes<br/>date=mon, 30 apr 2001 12:56:11 gmt<br/>etag=w/"02ca57e173c11:95b"<br/>content-type=application/octet-stream<br/>server=microsoft-iis/5.0<br/>last-modified=mon, 30 apr 2001 12:56:11 gmt<br/>
로그인 후 복사

사용 중단점 재개

GET /down.zip HTTP/1.0<br/>User-Agent: NetFox<br/>RANGE: bytes=2000070-<br/>Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2<br/>
로그인 후 복사

이런 추가 줄이 있습니다Range: bytes=2000070-<br/>

이 줄은 서버에 down.zip 파일이 2000070바이트부터 전송되며 이전 바이트는 전송할 필요가 없음을 알리는 의미입니다.
Range의 전체 형식은 다음과 같습니다.

Range: bytes=startOffset-targetOffset/sum [表示从startOffset读取,一直读取到targetOffset位置,读取总数为sum直接]<br/> <br/>Range: bytes=startOffset-targetOffset [字节总数也可以去掉]<br/>
로그인 후 복사

서버가 이 요청을 받은 후 반환되는 정보는 다음과 같습니다.

HTTP/1.1 206 Partial Content<br/>content-length=106786028<br/>content-range=bytes 2000070-106786027/106786028<br/>date=mon, 30 apr 2001 12:55:20 gmt<br/>etag=w/"02ca57e173c11:95b"<br/>content-type=application/octet-stream<br/>server=microsoft-iis/5.0<br/>last-modified=mon, 30 apr 2001 12:55:20 gmt<br/>
로그인 후 복사

이전 서버에서 반환된 정보와 비교하면 추가 행이 추가된 것을 확인할 수 있습니다.

Content-Range=bytes 2000070-106786027/106786028<br/>
로그인 후 복사

반환된 코드도 더 이상 200이 아닌 206으로 변경되었습니다.

HTTP/1.1 206 Partial Content<br/>
로그인 후 복사

위의 원칙을 알고 나면 이력서 전송을 프로그래밍할 수 있습니다.

2. PHP 구현

/** php下载类,支持断点续传<br/> * download: 下载文件<br/> * setSpeed: 设置下载速度<br/> * getRange: 获取header中Range<br/> */<br/> <br/>class FileDownload{<br/> <br/> /** 下载<br/> * @param String $file 要下载的文件路径<br/> * @param String $name 文件名称,为空则与下载的文件名称一样<br/> * @param boolean $reload 是否开启断点续传<br/> */<br/> public function download($file, $name=&#39;&#39;, $reload=false){<br/> $fp = @fopen($file, &#39;rb&#39;);<br/> if($fp){<br/> if($name==&#39;&#39;){<br/> $name = basename($file);<br/> }<br/> $header_array = get_headers($file, true);<br/> //var_dump($header_array);die;<br/> // 下载本地文件,获取文件大小<br/> if (!$header_array) {<br/> $file_size = filesize($file);<br/> } else {<br/> $file_size = $header_array[&#39;Content-Length&#39;];<br/> }<br/> $ranges = $this->getRange($file_size);<br/> $ua = $_SERVER["HTTP_USER_AGENT"];//判断是什么类型浏览器<br/> header(&#39;cache-control:public&#39;);<br/> header(&#39;content-type:application/octet-stream&#39;); <br/> <br/> $encoded_filename = urlencode($name);<br/> $encoded_filename = str_replace("+", "%20", $encoded_filename);<br/> <br/> //解决下载文件名乱码<br/> if (preg_match("/MSIE/", $ua) || preg_match("/Trident/", $ua) ){ <br/> header(&#39;Content-Disposition: attachment; filename="&#39; .$encoded_filename . &#39;"&#39;);<br/> } else if (preg_match("/Firefox/", $ua)) {<br/> header(&#39;Content-Disposition: attachment; filename*="utf8\&#39;\&#39;&#39; . $name . &#39;"&#39;);<br/> }else if (preg_match("/Chrome/", $ua)) {<br/> header(&#39;Content-Disposition: attachment; filename="&#39; . $encoded_filename . &#39;"&#39;);<br/> } else {<br/> header(&#39;Content-Disposition: attachment; filename="&#39; . $name . &#39;"&#39;);<br/> }<br/> //header(&#39;Content-Disposition: attachment; filename="&#39; . $name . &#39;"&#39;);<br/> <br/> if($reload && $ranges!=null){ // 使用续传<br/> header(&#39;HTTP/1.1 206 Partial Content&#39;);<br/> header(&#39;Accept-Ranges:bytes&#39;);<br/> <br/> // 剩余长度<br/> header(sprintf(&#39;content-length:%u&#39;,$ranges[&#39;end&#39;]-$ranges[&#39;start&#39;]));<br/> <br/> // range信息<br/> header(sprintf(&#39;content-range:bytes %s-%s/%s&#39;, $ranges[&#39;start&#39;], $ranges[&#39;end&#39;], $file_size));<br/> //file_put_contents(&#39;test.log&#39;,sprintf(&#39;content-length:%u&#39;,$ranges[&#39;end&#39;]-$ranges[&#39;start&#39;]),FILE_APPEND);<br/> // fp指针跳到断点位置<br/> fseek($fp, sprintf(&#39;%u&#39;, $ranges[&#39;start&#39;]));<br/> }else{<br/> file_put_contents(&#39;test.log&#39;,&#39;2222&#39;,FILE_APPEND);<br/> header(&#39;HTTP/1.1 200 OK&#39;);<br/> header(&#39;content-length:&#39;.$file_size);<br/> }<br/> <br/> while(!feof($fp)){<br/> //echo fread($fp, round($this->_speed*1024,0));<br/> //echo fread($fp, $file_size);<br/> echo fread($fp, 4096);<br/> ob_flush();<br/> }<br/> <br/> ($fp!=null) && fclose($fp);<br/> }else{<br/> return &#39;&#39;;<br/> }<br/> }<br/> <br/> /** 设置下载速度<br/> * @param int $speed<br/> */<br/> public function setSpeed($speed){<br/> if(is_numeric($speed) && $speed>16 && $speed<4096){<br/> $this->_speed = $speed;<br/> }<br/> }<br/> <br/> /** 获取header range信息<br/> * @param int $file_size 文件大小<br/> * @return Array<br/> */<br/> private function getRange($file_size){<br/> //file_put_contents(&#39;range.log&#39;, json_encode($_SERVER), FILE_APPEND);<br/> if(isset($_SERVER[&#39;HTTP_RANGE&#39;]) && !empty($_SERVER[&#39;HTTP_RANGE&#39;])){<br/> $range = $_SERVER[&#39;HTTP_RANGE&#39;];<br/> $range = preg_replace(&#39;/[\s|,].*/&#39;, &#39;&#39;, $range);<br/> $range = explode(&#39;-&#39;, substr($range, 6));<br/> if(count($range)<2){<br/> $range[1] = $file_size;<br/> }<br/> $range = array_combine(array(&#39;start&#39;,&#39;end&#39;), $range);<br/> if(empty($range[&#39;start&#39;])){<br/> $range[&#39;start&#39;] = 0;<br/> }<br/> if(empty($range[&#39;end&#39;])){<br/> $range[&#39;end&#39;] = $file_size;<br/> }<br/> return $range;<br/> }<br/> return null;<br/> }<br/>}<br/> <br/>$obj = new FileDownload();<br/>$obj->download(&#39;http://down.golaravel.com/laravel/laravel-master.zip&#39;,&#39;&#39;, true);<br/>
로그인 후 복사

추천 튜토리얼: "PHP"

위 내용은 PHP로 대용량 파일 업로드를 재개하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:jb51.net
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿