本文是为大家分享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 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';
}
*/
?>

以上就是本文的全部内容,希望对大家的学习有所帮助。

php支持断点续传、分块下载的类的更多相关文章

  1. iOS:调试无法在XCode中运行

    我正在使用XCode4和iOSSDK4.3.我的调试工作正常,但现在我发现在设置断点时,应用暂停,但XCode不关注编辑器中的行.点击断点时也不会显示绿色箭头.我有一个在AppDelegate中分配的UINavigationController.当我在didFinishLaunchingWithOptions中设置断点时,一切都按预期工作:这是当一个断点暂停了mapViewController中的

  2. ios – 异常断点处于活动状态时,应用程序在启动时崩溃

    我刚开始继续开发一款适用于商店的传统iPad应用程序.我注意到项目中的异常断点未启用.当我启用它时,应用程序在启动时崩溃,但在输出窗口中没有给出任何信息,而在线程视图中只有相当无用的信息(见下文)我试着解决它..>将Autolayout设置为关闭.>通过编辑和重新保存故事板文件..但到目前为止没有运气.我的猜测是,故事板中的某些内容被破坏了,因为AppDelegates“确实完成了启动……”

  3. xcode – 如何通过LLDB命令行添加断点操作?

    如果你从Xcode编辑一个断点,有一个超级有用的选项,可以添加一个“Action”,以便在每次遇到断点时自动执行.如何从LLDB命令行添加此类操作?

  4. xcode – 如何在LLDB断点条件下使用堆栈内容?

    问题:我有一种情况,我们在发布期间有媒体播放,并且objc_exception_throw()在此期间大约有5次点击,但总是被捕获,并且它在媒体播放器对象的南边.我厌倦了(a)必须手动连续n次,或者(b)在播放完成之前必须禁用断点.我尝试过的:>使断点忽略前五次命中(问题:它并不总是正好五次)>使用我的目标作为模块创建我自己的符号断点(问题:没有改变)我想做什么:想到的一个解决方案是在断点命中时评

  5. Xcode 4.3.1:在以下情况下不显示代码行:由于未捕获的异常而终止应用程序

    在Xcode的早期版本中,当我遇到崩溃时,Xcode通常会打开发生崩溃的文件,并经常将我带到崩溃的行.最新的Xcode似乎没有做那些让调试变得更难的东西.我是否需要启用一些新设置?

  6. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  7. 在Xcode中的选择器上添加符号断点

    我的应用程序中有一个错误,显示以下(部分)堆栈跟踪:为了调试这个,我决定在–[EventboolValue]上添加一个符号断点,推断当发送该选择器时,调试器将停止.然而,没有任何反应.设置断点后,应用程序只是士兵并生成相同的异常而不停止.我已经定义了断点如下:我正在使用LLDB调试器和Xcode4.2解决方法在选择器上设置断点会导致lldb在执行该选择器时停止,而不是在发送时停止.在你的情况下,没

  8. ios – 如何在Xcode 6中的异常断点上打印异常?

    我的应用程序正在崩溃,它似乎陷入了异常断点(这是有道理的),但我无法找到崩溃的原因.这是我尝试过的:>po$eax>po$rax>po$r0>po*(id*)($esp4)对于上述所有尝试,我收到以下错误:错误:使用未声明的标识符’$‘错误:解析表达式时出错1次我也找到了这个LLDBCommandGuide,但没有找到任何有用的东西(有点令人困惑,你不知道你在寻找什么)

  9. 从VS调试iOS时,程序’Mono’已从代码0(0x0)退出

    我有一个问题,当我尝试使用VS2013调试我的iOS应用程序时,我收到以下错误:Theprogram‘Mono’hasexitedwithcode0.我知道以下answer.清理解决方案确实解决了问题,但是下次调试时我需要再次执行…如果有人有长期解决方案,我们将非常感激.解决方法在发射期间它会崩溃吗?

  10. ios – Xcode中没有出现断点(9.3)

    st=jftp4n02&sh=49688058

随机推荐

  1. PHP个人网站架设连环讲(一)

    先下一个OmnihttpdProffesinalV2.06,装上就有PHP4beta3可以用了。PHP4给我们带来一个简单的方法,就是使用SESSION(会话)级变量。但是如果不是PHP4又该怎么办?我们可以假设某人在15分钟以内对你的网页的请求都不属于一个新的人次,这样你可以做个计数的过程存在INC里,在每一个页面引用,访客第一次进入时将访问时间送到cookie里。以后每个页面被访问时都检查cookie上次访问时间值。

  2. PHP函数学习之PHP函数点评

    PHP函数使用说明,应用举例,精简点评,希望对您学习php有所帮助

  3. ecshop2.7.3 在php5.4下的各种错误问题处理

    将方法内的函数,分拆为2个部分。这个和gd库没有一点关系,是ecshop程序的问题。会出现这种问题,不外乎就是当前会员的session或者程序对cookie的处理存在漏洞。进过本地测试,includes\modules\integrates\ecshop.php这个整合自身会员的类中没有重写integrate.php中的check_cookie()方法导致,验证cookie时返回的username为空,丢失了登录状态,在ecshop.php中重写了此方法就可以了。把他加到ecshop.php的最后面去就可

  4. NT IIS下用ODBC连接数据库

    $connection=intodbc_connect建立数据库连接,$query_string="查询记录的条件"如:$query_string="select*fromtable"用$cur=intodbc_exec检索数据库,将记录集放入$cur变量中。再用while{$var1=odbc_result;$var2=odbc_result;...}读取odbc_exec()返回的数据集$cur。最后是odbc_close关闭数据库的连接。odbc_result()函数是取当前记录的指定字段值。

  5. PHP使用JpGraph绘制折线图操作示例【附源码下载】

    这篇文章主要介绍了PHP使用JpGraph绘制折线图操作,结合实例形式分析了php使用JpGraph的相关操作技巧与注意事项,并附带源码供读者下载参考,需要的朋友可以参考下

  6. zen_cart实现支付前生成订单的方法

    这篇文章主要介绍了zen_cart实现支付前生成订单的方法,结合实例形式详细分析了zen_cart支付前生成订单的具体步骤与相关实现技巧,需要的朋友可以参考下

  7. Thinkphp5框架实现获取数据库数据到视图的方法

    这篇文章主要介绍了Thinkphp5框架实现获取数据库数据到视图的方法,涉及thinkPHP5数据库配置、读取、模型操作及视图调用相关操作技巧,需要的朋友可以参考下

  8. PHP+jquery+CSS制作头像登录窗(仿QQ登陆)

    本篇文章介绍了PHP结合jQ和CSS制作头像登录窗(仿QQ登陆),实现了类似QQ的登陆界面,很有参考价值,有需要的朋友可以了解一下。

  9. 基于win2003虚拟机中apache服务器的访问

    下面小编就为大家带来一篇基于win2003虚拟机中apache服务器的访问。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. Yii2中组件的注册与创建方法

    这篇文章主要介绍了Yii2之组件的注册与创建的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下

返回
顶部