Maison  >  Article  >  développement back-end  >  Classe de téléchargement de fichiers PHP prenant en charge le téléchargement de la reprise du point d'arrêt

Classe de téléchargement de fichiers PHP prenant en charge le téléchargement de la reprise du point d'arrêt

黄舟
黄舟original
2017-02-18 09:30:471460parcourir

php prend en charge la reprise du point d'arrêt, en s'appuyant principalement sur l'en-tête HTTP_RANGE dans le protocole HTTP.

Principe de téléchargement de reprise de point d'arrêt HTTP
Plage d'en-tête HTTP, Content-Range()
Utilisé uniquement pour les téléchargements de points d'arrêt généraux dans la plage d'en-tête HTTP et En-têtes d'entité Content-Range,
En-tête de demande utilisateur Range, spécifiez la position du premier octet et la position du dernier octet, par exemple (Range : 200-300)
Content-Range est utilisé pour l'en-tête de réponse

demandes de téléchargement de l'intégralité du fichier :
GET /test.rar HTTP/1.1
Connexion : fermer
Hôte : 116.1.219.219
Plage : octets=0-801 //Général La demande de téléchargement du fichier entier est bytes=0- ou ne pas utiliser cet en-tête

Réponse généralement normale
HTTP/1.1 200 OK
Content-Length : 801
Content-Type : application /octet-stream
Content-Range : octets 0-800/801 //801 : taille totale du fichier

FileDownload.class.php

<?php
/** php下载类,支持断点续传
*   Date:   2013-06-30
*   Author: fdipzone
*   Ver:    1.0
*
*   Func:
*   download: 下载文件
*   setSpeed: 设置下载速度
*   getRange: 获取header中Range
*/

class FileDownload{ // class start

    private $_speed = 512;   // 下载速度


    /** 下载
    * @param String  $file   要下载的文件路径
    * @param String  $name   文件名称,为空则与下载的文件名称一样
    * @param boolean $reload 是否开启断点续传
    */
    public function download($file, $name=&#39;&#39;, $reload=false){
        if(file_exists($file)){
            if($name==&#39;&#39;){
                $name = basename($file);
            }

            $fp = fopen($file, &#39;rb&#39;);
            $file_size = filesize($file);
            $ranges = $this->getRange($file_size);

            header(&#39;cache-control:public&#39;);
            header(&#39;content-type:application/octet-stream&#39;);
            header(&#39;content-disposition:attachment; filename=&#39;.$name);

            if($reload && $ranges!=null){ // 使用续传
                header(&#39;HTTP/1.1 206 Partial Content&#39;);
                header(&#39;Accept-Ranges:bytes&#39;);
                
                // 剩余长度
                header(sprintf(&#39;content-length:%u&#39;,$ranges[&#39;end&#39;]-$ranges[&#39;start&#39;]));
                
                // range信息
                header(sprintf(&#39;content-range:bytes %s-%s/%s&#39;, $ranges[&#39;start&#39;], $ranges[&#39;end&#39;], $file_size));
                
                // fp指针跳到断点位置
                fseek($fp, sprintf(&#39;%u&#39;, $ranges[&#39;start&#39;]));
            }else{
                header(&#39;HTTP/1.1 200 OK&#39;);
                header(&#39;content-length:&#39;.$file_size);
            }

            while(!feof($fp)){
                echo fread($fp, round($this->_speed*1024,0));
                ob_flush();
                //sleep(1); // 用于测试,减慢下载速度
            }

            ($fp!=null) && fclose($fp);

        }else{
            return &#39;&#39;;
        }
    }


    /** 设置下载速度
    * @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){
        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;
    }

} // class end

?>

démo

<?php

require(&#39;FileDownload.class.php&#39;);
$file = &#39;book.zip&#39;;
$name = time().&#39;.zip&#39;;
$obj = new FileDownload();
$flag = $obj->download($file, $name);
//$flag = $obj->download($file, $name, true); // 断点续传

if(!$flag){
    echo &#39;file not exists&#39;;
}

?>

Méthode de test de reprise du point d'arrêt :
Utilisez la commande Linux wget pour tester le téléchargement, wget -c -O fichier http://www.php.cn/

1. Désactivez d'abord la reprise du point d'arrêt
$flag = $obj->download($file, $name);

fdipzone@ubuntu:~/Downloads$ wget -O test.rar http://www.php.cn/
--2013-06-30 16:52:44--  http://www.php.cn/
正在解析主机 demo.fdipzone.com... 127.0.0.1
正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 10445120 (10.0M) [application/octet-stream]
正在保存至: “test.rar”

30% [============================>                                                                     ] 3,146,580    513K/s  估时 14s
^C
fdipzone@ubuntu:~/Downloads$ wget -c -O test.rar http://www.php.cn/
--2013-06-30 16:52:57--  http://www.php.cn/
正在解析主机 demo.fdipzone.com... 127.0.0.1
正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 10445120 (10.0M) [application/octet-stream]
正在保存至: “test.rar”

30% [============================>                                                                     ] 3,146,580    515K/s  估时 14s
^C

可以看到,wget -c不能断点续传


2. Activer la reprise du point d'arrêt
$flag = $obj->download($file, $name, true);

fdipzone@ubuntu:~/Downloads$ wget -O test.rar http://www.php.cn/
--2013-06-30 16:53:19--  http://www.php.cn/
正在解析主机 demo.fdipzone.com... 127.0.0.1
正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 10445120 (10.0M) [application/octet-stream]
正在保存至: “test.rar”

20% [==================>                                                                               ] 2,097,720    516K/s  估时 16s
^C
fdipzone@ubuntu:~/Downloads$ wget -c -O test.rar http://www.php.cn/
--2013-06-30 16:53:31--  http://www.php.cn/
正在解析主机 demo.fdipzone.com... 127.0.0.1
正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 206 Partial Content
长度: 10445121 (10.0M),7822971 (7.5M) 字节剩余 [application/octet-stream]
正在保存至: “test.rar”

100%[++++++++++++++++++++++++=========================================================================>] 10,445,121   543K/s   花时 14s   

2013-06-30 16:53:45 (543 KB/s) - 已保存 “test.rar” [10445121/10445121])

可以看到会从断点的位置(%20)开始下载。


Ce qui précède est le contenu du téléchargement de fichiers PHP qui prend en charge la reprise du point d'arrêt. Pour plus de contenu connexe, veuillez prêter attention à. Site Web chinois PHP (www.php.cn) !


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn