File Download Class Supporting Breakpoint Continued Transfer Implemented by php

  • 2021-07-21 07:54:33
  • OfStack

This article describes the example of php to support the breakpoint continued transmission of the file download class and its usage, is a very practical skills. Share it for your reference. The specific methods are as follows:

Generally speaking, php supports breakpoint continuous transmission, which is mainly implemented by header HTTP_RANGE in HTTP protocol.

Principle of HTTP breakpoint continuous transmission:

Http header Range, Content-Range ()
Range and Content-Range entity headers are only used when downloading one breakpoint in HTTP header,
In the Range user request header, specify the position of the first byte and the position of the last byte, such as (Range: 200-300)
Content-Range for response headers

Request to download the entire file:

GET /test.rar HTTP/1.1
Connection: close
Host: 116.1.219.219
Range: bytes=0-801//1 Request to download the entire file is bytes=0-or without this header

1 normal response:

HTTP/1.1 200 OK
Content-Length: 801
Content-Type: application/octet-stream
Content-Range: bytes 0-800/801//801: Total file size

The code for the FileDownload. class. php class file is as follows:


<?php 
/** php Download class , Support breakpoint continuous transmission  
*  Date:  2013-06-30 
*  Author: test 
*  Ver:  1.0 
* 
*  Func: 
*  download:  Download a file  
*  setSpeed:  Set the download speed  
*  getRange:  Get header Medium Range 
*/ 
 
class FileDownload{ // class start 
 
  private $_speed = 512;  //  Download speed  
 
  /**  Download  
  * @param String $file   The file path to download  
  * @param String $name   File name , If it is empty, it is the same as the downloaded file name 1 Sample  
  * @param boolean $reload  Whether to turn on breakpoint resume transmission  
  */ 
  public function download($file, $name='', $reload=false){ 
    if(file_exists($file)){ 
      if($name==''){ 
        $name = basename($file); 
      } 
 
      $fp = fopen($file, 'rb'); 
      $file_size = filesize($file); 
      $ranges = $this->getRange($file_size); 
 
      header('cache-control:public'); 
      header('content-type:application/octet-stream'); 
      header('content-disposition:attachment; filename='.$name); 
 
      if($reload && $ranges!=null){ //  Use continued transmission  
        header('HTTP/1.1 206 Partial Content'); 
        header('Accept-Ranges:bytes'); 
         
        //  Remaining length  
        header(sprintf('content-length:%u',$ranges['end']-$ranges['start'])); 
         
        // range Information  
        header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size)); 
         
        // fp The pointer skips to the breakpoint position  
        fseek($fp, sprintf('%u', $ranges['start'])); 
      }else{ 
        header('HTTP/1.1 200 OK'); 
        header('content-length:'.$file_size); 
      } 
 
      while(!feof($fp)){ 
        echo fread($fp, round($this->_speed*1024,0)); 
        ob_flush(); 
        //sleep(1); //  Used for testing , Slow down the download speed  
      } 
 
      ($fp!=null) && fclose($fp); 
 
    }else{ 
      return ''; 
    } 
  } 
 
  /**  Set the download speed  
  * @param int $speed 
  */ 
  public function setSpeed($speed){ 
    if(is_numeric($speed) && $speed>16 && $speed<4096){ 
      $this->_speed = $speed; 
    } 
  } 
 
  /**  Get header range Information  
  * @param int  $file_size  File size  
  * @return Array 
  */ 
  private function getRange($file_size){ 
    if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])){ 
      $range = $_SERVER['HTTP_RANGE']; 
      $range = preg_replace('/[\s|,].*/', '', $range); 
      $range = explode('-', substr($range, 6)); 
      if(count($range)<2){ 
        $range[1] = $file_size; 
      } 
      $range = array_combine(array('start','end'), $range); 
      if(empty($range['start'])){ 
        $range['start'] = 0; 
      } 
      if(empty($range['end'])){ 
        $range['end'] = $file_size; 
      } 
      return $range; 
    } 
    return null; 
  } 
} // class end 
 
?> 

The sample code for demo is as follows:


<?php 
require('FileDownload.class.php'); 
$file = 'book.zip'; 
$name = time().'.zip'; 
$obj = new FileDownload(); 
$flag = $obj->download($file, $name); 
//$flag = $obj->download($file, $name, true); //  Breakpoint transmission  
 
if(!$flag){ 
  echo 'file not exists'; 
} 
?>

Breakpoint continuous transmission test method:

Use the linux wget command to test the download, wget-c-O file http://xxx

1. Close the breakpoint and continue transmission first


$flag = $obj->download($file, $name);

test@ubuntu:~/Downloads$ wget -O test.rar http://demo.test.com/demo.php 
--2013-06-30 16:52:44-- http://demo.test.com/demo.php 
 Resolving host  demo.test.com... 127.0.0.1 
 Connecting  demo.test.com|127.0.0.1|:80...  Already connected.  
 Issued  HTTP  Request, waiting for response ... 200 OK 
 Length:  10445120 (10.0M) [application/octet-stream] 
 Saving to :  " test.rar "  
 
30% [============================>                                   ] 3,146,580  513K/s  Estimated time  14s 
^C 
test@ubuntu:~/Downloads$ wget -c -O test.rar http://demo.test.com/demo.php 
--2013-06-30 16:52:57-- http://demo.test.com/demo.php 
 Resolving host  demo.test.com... 127.0.0.1 
 Connecting  demo.test.com|127.0.0.1|:80...  Already connected.  
 Issued  HTTP  Request, waiting for response ... 200 OK 
 Length:  10445120 (10.0M) [application/octet-stream] 
 Saving to :  " test.rar "  
30% [============================>                                   ] 3,146,580  515K/s  Estimated time  14s 
^C 

It can be seen that wget-c cannot be continued at breakpoint

2. Open the breakpoint to continue transmission


$flag = $obj->download($file, $name, true);

test@ubuntu:~/Downloads$ wget -O test.rar http://demo.test.com/demo.php 
--2013-06-30 16:53:19-- http://demo.test.com/demo.php 
 Resolving host  demo.test.com... 127.0.0.1 
 Connecting  demo.test.com|127.0.0.1|:80...  Already connected.  
 Issued  HTTP  Request, waiting for response ... 200 OK 
 Length:  10445120 (10.0M) [application/octet-stream] 
 Saving to :  " test.rar "  
 
20% [==================>                                        ] 2,097,720  516K/s  Estimated time  16s 
^C 
test@ubuntu:~/Downloads$ wget -c -O test.rar http://demo.test.com/demo.php 
--2013-06-30 16:53:31-- http://demo.test.com/demo.php 
 Resolving host  demo.test.com... 127.0.0.1 
 Connecting  demo.test.com|127.0.0.1|:80...  Already connected.  
 Issued  HTTP  Request, waiting for response ... 206 Partial Content 
 Length:  10445121 (10.0M) , 7822971 (7.5M)  Byte residue  [application/octet-stream] 
 Saving to :  " test.rar "  
 
100%[++++++++++++++++++++++++=========================================================================>] 10,445,121  543K/s   Flower time  14s   
 
2013-06-30 16:53:45 (543 KB/s) -  Saved   " test.rar "  [10445121/10445121]) 

You can see that the download will begin at the location of the breakpoint (% 20).

The complete source code of this example can be downloaded here.

I believe that this paper has a certain reference value for everyone's PHP programming.


Related articles: