Heim  >  Artikel  >  Backend-Entwicklung  >  Wie kann ich das Hochladen großer Dateien mit PHP fortsetzen?

Wie kann ich das Hochladen großer Dateien mit PHP fortsetzen?

Guanhui
Guanhuinach vorne
2020-06-28 18:13:282469Durchsuche

Wie kann ich das Hochladen großer Dateien mit PHP fortsetzen?

1. Prinzip des fortsetzbaren Downloads

Der sogenannte fortsetzbare Download bedeutet, dass die Datei heruntergeladen werden muss Wo kann der Download fortgesetzt werden? Haltepunkte wurden in früheren Versionen des HTTP-Protokolls nicht unterstützt, werden aber seit HTTP/1.1 unterstützt. Im Allgemeinen werden die Entitätsheader „Range“ und „Content-Range“ nur zum Herunterladen von Haltepunkten verwendet.

Verwenden Sie keine Haltepunktwiederaufnahme

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/>

Nachdem der Server die Anforderung erhalten hat, sucht er nach Bedarf nach der angeforderten Datei, extrahiert die Dateiinformationen und gibt sie dann an den Browser zurück lautet wie folgt:

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/>

Breakpoint-Wiederaufnahme verwenden

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/>

Es gibt diese zusätzliche ZeileRange: bytes=2000070-<br>

Diese Zeile bedeutet, dem Server mitzuteilen, dass die Datei down.zip sein wird Hochgeladen ab 2000070 Bytes. Es besteht keine Notwendigkeit, Bytes zu übertragen. Das vollständige Format von
Range lautet:

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

Nachdem der Server diese Anfrage erhalten hat, lauten die zurückgegebenen Informationen wie folgt:

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/>

Vergleichen Sie sie mit den vom vorherigen Server zurückgegebenen Informationen und Sie werden feststellen, dass eine zusätzliche Zeile hinzugefügt wurde:

Content-Range=bytes 2000070-106786027/106786028<br/>

Der zurückgegebene Code wurde ebenfalls in 206 statt 200 geändert.

HTTP/1.1 206 Partial Content<br/>

Nachdem Sie die oben genannten Grundsätze kennen, können Sie die Übertragung des Lebenslaufs programmieren.

2. PHP-Implementierung

/** 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/>

Empfohlenes Tutorial: „PHP

Das obige ist der detaillierte Inhalt vonWie kann ich das Hochladen großer Dateien mit PHP fortsetzen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:jb51.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen
Vorheriger Artikel:Was ist der JIT von PHP8?Nächster Artikel:Was ist der JIT von PHP8?