欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  php教程

PHP支持断点续传,分块下载的类

程序员文章站 2022-03-17 10:45:14
...
 '*/*',
            'User-Agent'      => 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
            'Accept-Encoding' => 'gzip, deflate',
            'Host'            => $url_info['host'],
            'Connection'      => 'Close',
            'Accept-Language' => 'zh-cn',
        );
 
        // merge heade
        $headers = array_merge($def_headers, $headers);
        // get content length
        $content_length = self::get_content_size($url_info['host'], $url_info['port'], $url_info['request'], $headers, $timeout);
 
        // content length not exist
        if (!$content_length) {
            throw new Exception('Content-Length is Not Exists');
        }
        // get exists length
        $exists_length = is_file($save_file) ? filesize($save_file) : 0;
        // get tmp data file
        $data_file = $save_file . '.data';
        // get tmp data
        $exists_data = is_file($data_file) ? json_decode(file_get_contents($data_file), 1) : array();
        // check file is valid
        if ($exists_length == $content_length) {
            $exists_data && @unlink($data_file);
            return true;
        }
        // check file is expire
        if ($exists_data['length'] != $content_length || $exists_length > $content_length) {
            $exists_data = array(
                'length' => $content_length,
            );
        }
        // write exists data
        file_put_contents($data_file, json_encode($exists_data));
 
        try {
            $download_status = self::download_content($url_info['host'], $url_info['port'], $url_info['request'], $save_file, $content_length, $exists_length, $speed, $headers, $timeout);
            if ($download_status) {
                @unlink($data_file);
            }
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        return true;
    }
 
    /**
     * parse url
     *
     * @param $url
     * @return bool|mixed
     */
    static function parse_url($url) {
        $url_info = parse_url($url);
        if (!$url_info['host']) {
            return false;
        }
        $url_info['port']    = $url_info['port'] ? $url_info['host'] : 80;
        $url_info['request'] = $url_info['path'] . ($url_info['query'] ? '?' . $url_info['query'] : '');
        return $url_info;
    }
 
    /**
     * download content by chunk
     *
     * @param $host
     * @param $port
     * @param $url_path
     * @param $headers
     * @param $timeout
     */
    static function download_content($host, $port, $url_path, $save_file, $content_length, $range_start, $speed, &$headers, $timeout) {
        $request = self::build_header('GET', $url_path, $headers, $range_start);
        $fsocket = @fsockopen($host, $port, $errno, $errstr, $timeout);
        stream_set_blocking($fsocket, TRUE);
        stream_set_timeout($fsocket, $timeout);
        fwrite($fsocket, $request);
        $status = stream_get_meta_data($fsocket);
        if ($status['timed_out']) {
            throw new Exception('Socket Connect Timeout');
        }
        $is_header_end = 0;
        $total_size    = $range_start;
        $file_fp       = fopen($save_file, 'a+');
        while (!feof($fsocket)) {
            if (!$is_header_end) {
                $line = @fgets($fsocket);
                if (in_array($line, array("\n", "\r\n"))) {
                    $is_header_end = 1;
                }
                continue;
            }
            $resp        = fread($fsocket, $speed);
            $read_length = strlen($resp);
            if ($resp === false || $content_length  $hval) {
            $out .= $hkey . ': ' . $hval . "\r\n";
        }
        if ($range_start > -1) {
            $out .= "Accept-Ranges: bytes\r\n";
            $out .= "Range: bytes={$range_start}-\r\n";
        }
        $out .= "\r\n";
 
        return $out;
    }
}
 
 
#use age
/*
try {
    if (downloader::get('http://dzs.aqtxt.com/files/11/23636/201604230358308081.rar', 'test.rar')) {
        //todo
        echo 'Download Succ';
    }
} catch (Exception $e) {
    echo 'Download Failed';
}
*/
?>