亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長(zhǎng)資訊網(wǎng)
    最全最豐富的資訊網(wǎng)站

    PHP如何實(shí)現(xiàn)斷點(diǎn)續(xù)傳大文件?

    PHP如何實(shí)現(xiàn)斷點(diǎn)續(xù)傳大文件?

    一、斷點(diǎn)續(xù)傳原理

    所謂斷點(diǎn)續(xù)傳,也就是要從文件已經(jīng)下載的地方開始繼續(xù)下載。在以前版本的 HTTP 協(xié)議是不支持?jǐn)帱c(diǎn)的,HTTP/1.1 開始就支持了。一般斷點(diǎn)下載時(shí)才用到 Range 和 Content-Range 實(shí)體頭。

    不使用斷點(diǎn)續(xù)傳

    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

    服務(wù)器收到請(qǐng)求后,按要求尋找請(qǐng)求的文件,提取文件的信息,然后返回給瀏覽器,返回信息如下:

    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

    使用斷點(diǎn)續(xù)傳

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

    多了這么一行Range: bytes=2000070-

    這一行的意思就是告訴服務(wù)器down.zip這個(gè)文件從2000070字節(jié)開始傳,前面的字節(jié)不用傳了。
    Range的完整格式是:

    Range: bytes=startOffset-targetOffset/sum [表示從startOffset讀取,一直讀取到targetOffset位置,讀取總數(shù)為sum直接]

    Range: bytes=startOffset-targetOffset [字節(jié)總數(shù)也可以去掉]

    服務(wù)器收到這個(gè)請(qǐng)求以后,返回的信息如下:

    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

    和前面服務(wù)器返回的信息比較一下,就會(huì)發(fā)現(xiàn)增加了一行:

    Content-Range=bytes 2000070-106786027/106786028

    返回的代碼也改為206了,而不再是200了。

    HTTP/1.1 206 Partial Content

    知道了以上原理,就可以進(jìn)行斷點(diǎn)續(xù)傳的編程了。

    二、PHP實(shí)現(xiàn)

    /** php下載類,支持?jǐn)帱c(diǎn)續(xù)傳
    * download: 下載文件
    * setSpeed: 設(shè)置下載速度
    * getRange: 獲取header中Range
    */

    class FileDownload{

    /** 下載
    * @param String $file 要下載的文件路徑
    * @param String $name 文件名稱,為空則與下載的文件名稱一樣
    * @param boolean $reload 是否開啟斷點(diǎn)續(xù)傳
    */
    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){ // 使用續(xù)傳
    header('HTTP/1.1 206 Partial Content');
    header('Accept-Ranges:bytes');

    // 剩余長(zhǎng)度
    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指針跳到斷點(diǎn)位置
    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 '';
    }
    }

    /** 設(shè)置下載速度
    * @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('range.log', json_encode($_SERVER), FILE_APPEND);
    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;
    }
    }

    $obj = new FileDownload();
    $obj->download('http://down.golaravel.com/laravel/laravel-master.zip','', true);

    推薦教程:《PHP》

    贊(0)
    分享到: 更多 (0)
    網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)