php支持?jǐn)帱c(diǎn)續(xù)傳、分塊下載的類
本文是為大家分享php支持?jǐn)帱c(diǎn)續(xù)傳、分塊下載的類,供大家參考,具體內(nèi)容如下
<?php /** * User: djunny * Date: 2016-04-29 * Time: 17:18 * Mail: 199962760@qq.com * 支持?jǐn)帱c(diǎn)下載的類 */ class downloader { /** * download file to local path * * @param $url * @param $save_file * @param int $speed * @param array $headers * @param int $timeout * @return bool * @throws Exception */ static function get($url, $save_file, $speed = 10240, $headers = array(), $timeout = 10) { $url_info = self::parse_url($url); if (!$url_info['host']) { throw new Exception('Url is Invalid'); } // default header $def_headers = array( 'Accept' => '*/*', '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 < $total_size + $read_length) { fclose($fsocket); fclose($file_fp); throw new Exception('Socket I/O Error Or File Was Changed'); } $total_size += $read_length; fputs($file_fp, $resp); // check file end if ($content_length == $total_size) { break; } sleep(1); // for test //break; } fclose($fsocket); fclose($file_fp); return true; } /** * get content length * * @param $host * @param $port * @param $url_path * @param $headers * @param $timeout * @return int */ static function get_content_size($host, $port, $url_path, &$headers, $timeout) { $request = self::build_header('HEAD', $url_path, $headers); $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); $length = 0; if ($status['timed_out']) { return 0; } while (!feof($fsocket)) { $line = @fgets($fsocket); if (in_array($line, array("\n", "\r\n"))) { break; } $line = strtolower($line); // get location if (substr($line, 0, 9) == 'location:') { $location = trim(substr($line, 9)); $url_info = self::parse_url($location); if (!$url_info['host']) { return 0; } fclose($fsocket); return self::get_content_size($url_info['host'], $url_info['port'], $url_info['request'], $headers, $timeout); } // get content length if (strpos($line, 'content-length:') !== false) { list(, $length) = explode('content-length:', $line); $length = (int)trim($length); } } fclose($fsocket); return $length; } /** * build header for socket * * @param $action * @param $url_path * @param $headers * @param int $range_start * @return string */ static function build_header($action, $url_path, &$headers, $range_start = -1) { $out = $action . " {$url_path} HTTP/1.0\r\n"; foreach ($headers as $hkey => $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'; } */ ?>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
- php斷點(diǎn)續(xù)傳之如何分割合并文件
- 解決PHP超大文件下載,斷點(diǎn)續(xù)傳下載的方法詳解
- php實(shí)現(xiàn)的支持?jǐn)帱c(diǎn)續(xù)傳的文件下載類
- php下載遠(yuǎn)程文件類(支持?jǐn)帱c(diǎn)續(xù)傳)
- PHP實(shí)現(xiàn)HTTP斷點(diǎn)續(xù)傳的方法
- php斷點(diǎn)續(xù)傳之文件分割合并詳解
- 關(guān)于php支持分塊與斷點(diǎn)續(xù)傳文件下載功能代碼
- php+resumablejs實(shí)現(xiàn)的分塊上傳 斷點(diǎn)續(xù)傳功能示例
- PHP簡(jiǎn)單實(shí)現(xiàn)斷點(diǎn)續(xù)傳下載的方法
- PHP實(shí)現(xiàn)斷點(diǎn)續(xù)傳亂序合并文件的方法
相關(guān)文章
php編寫的抽獎(jiǎng)程序中獎(jiǎng)概率算法
本文給大家分享的是php中獎(jiǎng)概率算法,可用于刮刮卡,大轉(zhuǎn)盤等抽獎(jiǎng)算法。用法很簡(jiǎn)單,代碼里有詳細(xì)注釋說(shuō)明,一看就懂,有需要的小伙伴參考下吧。2015-05-05PHP郵件群發(fā)機(jī)實(shí)現(xiàn)代碼
這篇文章主要介紹了PHP郵件群發(fā)機(jī)實(shí)現(xiàn)代碼,需要的朋友可以參考下2016-02-02解析PHP SPL標(biāo)準(zhǔn)庫(kù)的用法(遍歷目錄,查找固定條件的文件)
本篇文章是對(duì)PHP中SPL標(biāo)準(zhǔn)庫(kù)的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06如何用PHP編寫簡(jiǎn)單的api數(shù)據(jù)接口
這篇文章主要介紹了如何用PHP編寫簡(jiǎn)單的api數(shù)據(jù)接口,對(duì)數(shù)據(jù)接口感興趣的同學(xué),可以參考一下,并且親自試驗(yàn)一下2021-04-04PHP對(duì)文件進(jìn)行加鎖、解鎖實(shí)例
這篇文章主要介紹了PHP對(duì)文件進(jìn)行加鎖、解鎖實(shí)例,本文直接給出實(shí)現(xiàn)代碼和代碼的使用方法,需要的朋友可以參考下2015-01-01php download.php實(shí)現(xiàn)代碼 跳轉(zhuǎn)到下載文件(response.redirect)
一直對(duì)php不太熟悉,今天需要類型asp的 response.redirect語(yǔ)句,但一直沒有很好的解決方法。下面是問(wèn)了朋友才知道的。2009-08-08php實(shí)現(xiàn)基于pdo的事務(wù)處理方法示例
這篇文章主要介紹了php實(shí)現(xiàn)基于pdo的事務(wù)處理方法,結(jié)合實(shí)例形式分析了php使用pdo進(jìn)行事務(wù)操作的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-07-07