Heim >Backend-Entwicklung >PHP-Tutorial >PHP implementiert den Haltepunkt zum Fortsetzen des Hochladens großer Dateien

PHP implementiert den Haltepunkt zum Fortsetzen des Hochladens großer Dateien

藏色散人
藏色散人nach vorne
2020-12-30 08:59:514604Durchsuche

Empfohlen: „PHP-Video-Tutorial

1. Prinzip des fortsetzbaren Downloads

Der sogenannte fortsetzbare Download bedeutet, den Download an der Stelle fortzusetzen, an der die Datei heruntergeladen wurde. 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
accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
accept-language: zh-cn
accept-encoding: gzip, deflate
user-agent: mozilla/4.0 (compatible; msie 5.01; windows nt 5.0)
connection: keep-alive

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. Die Rückgabeinformationen lauten wie folgt:

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

Verwenden Wiederaufnahme des Haltepunkts

GET /down.zip HTTP/1.0
User-Agent: NetFox
RANGE: bytes=2000070-
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2

Es ​​gibt so eine zusätzliche ZeileRange: bytes=2000070-

Diese Zeile bedeutet, dem Server mitzuteilen, dass die Datei down.zip ab 2000070 Bytes übertragen wird und die vorherigen Bytes nicht übertragen werden müssen. Das vollständige Format von
Range lautet:

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

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

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

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

Content-Range=bytes 2000070-106786027/106786028

Der zurückgegebene Code wurde ebenfalls in 206 geändert, nicht mehr in 200.

HTTP/1.1 206 Partial Content

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

2. PHP-Implementierung

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

Das obige ist der detaillierte Inhalt vonPHP implementiert den Haltepunkt zum Fortsetzen des Hochladens großer Dateien. 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