Welcome 微信登录

首页 / 网页编程 / PHP / php支持断点续传、分块下载的类

本文是为大家分享php支持断点续传、分块下载的类,供大家参考,具体内容如下
<?php /** * User: djunny * Date: 2016-04-29 * Time: 17:18 * Mail: 199962760@qq.com * 支持断点下载的类 */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 existif (!$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 validif ($exists_length == $content_length) {$exists_data && @unlink($data_file);return true;}// check file is expireif ($exists_data["length"] != $content_length || $exists_length > $content_length) {$exists_data = array("length" => $content_length,);}// write exists datafile_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("
", "
"))) {$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 endif ($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("
", "
"))) {break;}$line = strtolower($line);// get locationif (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 lengthif (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
";foreach ($headers as $hkey => $hval) {$out .= $hkey . ": " . $hval . "
";}if ($range_start > -1) {$out .= "Accept-Ranges: bytes
";$out .= "Range: bytes={$range_start}-
";}$out .= "
"; return $out;}}#use age/*try {if (downloader::get("http://dzs.aqtxt.com/files/11/23636/201604230358308081.rar", "test.rar")) {//todoecho "Download Succ";}} catch (Exception $e) {echo "Download Failed";}*/?>
以上就是本文的全部内容,希望对大家的学习有所帮助。