>  기사  >  백엔드 개발  >  중단점 이력서 다운로드를 지원하는 PHP 파일 다운로드 클래스

중단점 이력서 다운로드를 지원하는 PHP 파일 다운로드 클래스

黄舟
黄舟원래의
2017-02-18 09:30:471415검색

php는 주로 HTTP 프로토콜의 HTTP_RANGE 헤더에 의존하여 중단점 재개를 지원합니다.

HTTP 중단점 재개 다운로드 원칙
Http 헤더 범위, Content-Range()
HTTP 헤더 범위 및 일반 중단점 다운로드에만 사용됩니다. Content-Range 엔터티 헤더,
Range 사용자 요청 헤더는 (Range: 200-300)과 같이 첫 번째 바이트의 위치와 마지막 바이트의 위치를 ​​지정합니다.
Content-Range는 응답 헤더에 사용됩니다. 🎜>
전체 파일 다운로드 요청:
GET /test.rar HTTP/1.1
연결: 닫기
호스트: 116.1.219.219
범위: 바이트=0-801 //일반 전체 파일 다운로드 요청은 bytes=0- 또는 이 헤더를 사용하지 마십시오

일반적으로 정상적인 응답
HTTP/1.1 200 OK
Content-Length: 801
Content-Type: application /octet-stream
Content-Range: 바이트 0-800/801 //801: 총 파일 크기


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

?>

demo

<?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;;
}

?>

중단점 재개 테스트 방법: linux
wget 명령을 사용하여 다운로드를 테스트합니다. wget -c -O 파일 http://www.php.cn/

1. 닫기 먼저 중단점을 설정하고 계속 진행 $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. 연결 해제를 켭니다. 재개하려면 클릭하세요 $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)开始下载。


위는 중단점 재개를 지원하는 PHP 파일 다운로드 내용입니다. 자세한 내용은 PHP를 참고해주세요. 중국사이트(www.php.cn)!



성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.