zoukankan      html  css  js  c++  java
  • php开启多线程下载

    php开启多线程下载


    <pre>
    <?php
    /**
    * 多进程批量下载文件(使用php curl_multi_exec实现)
    * Date: 2017-07-16
    * Author: fdipzone
    * Version: 1.0
    *
    * Func
    * public download 下载处理
    * public process 多进程下载
    * private to_log 将执行结果写入日志文件
    */
    class BatchDownLoad {

    // 下载文件设置
    private $download_config = array();

    // 最大开启进程数量
    private $max_process_num = 10;

    // 超时秒数
    private $timeout = 10;

    // 日志文件
    private $logfile = null;

    /**
    * 初始化
    * @param Array $download_config 下载的文件设置
    * @param Int $max_process_num 最大开启的进程数量
    * @param Int $timeout 超时秒数
    * @param String $logfile 日志文件路径
    */
    public function __construct($download_config, $max_process_num=10, $timeout=10, $logfile=''){
    $this->download_config = $download_config;
    $this->max_process_num = $max_process_num;
    $this->timeout = $timeout;

    // 日志文件
    if($logfile){
    $this->logfile = $logfile;
    }else{
    $this->logfile = dirname(__FILE__).'/batch_download_'.date('Ymd').'.log';
    }
    }

    /**
    * 执行下载
    * @result Int
    */
    public function download(){

    // 已处理的数量
    $handle_num = 0;

    // 未处理完成
    while(count($this->download_config)>0){

    // 需要处理的大于最大进程数
    if(count($this->download_config)>$this->max_process_num){
    $process_num = $this->max_process_num;
    // 需要处理的小于最大进程数
    }else{
    $process_num = count($this->download_config);
    }

    // 抽取指定数量进行下载
    $tmp_download_config = array_splice($this->download_config, 0, $process_num);

    // 执行下载
    $result = $this->process($tmp_download_config);

    // 写入日志
    $this->to_log($tmp_download_config, $result);

    // 记录已处理的数量
    $handle_num += count($result);

    }

    return $handle_num;

    }

    /**
    * 多进程下载文件
    * @param Array $download_config 本次下载的设置
    * @return Array
    */
    public function process($download_config){

    // 文件资源
    $fp = array();

    // curl会话
    $ch = array();

    // 执行结果
    $result = array();

    // 创建curl handle
    $mh = curl_multi_init();

    // 循环设定数量
    foreach($download_config as $k=>$config){
    $ch[$k] = curl_init();
    $fp[$k] = fopen($config[1], 'a');

    curl_setopt($ch[$k], CURLOPT_URL, $config[0]);
    curl_setopt($ch[$k], CURLOPT_FILE, $fp[$k]);
    curl_setopt($ch[$k], CURLOPT_HEADER, 0);
    curl_setopt($ch[$k], CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch[$k], CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)');

    // 加入处理
    curl_multi_add_handle($mh, $ch[$k]);
    }
    //下面几句话就是执行多线程curl 不用理解为什么这样写 照着写就是了 如果执行好 $active会变成0的
    $active = null;

    do{
    $mrc = curl_multi_exec($mh, $active);
    } while($active);

    // 获取数据
    foreach($fp as $k=>$v){
    fwrite($v, curl_multi_getcontent($ch[$k]));
    }

    // 关闭curl handle与文件资源
    foreach($download_config as $k=>$config){
    curl_multi_remove_handle($mh, $ch[$k]);
    fclose($fp[$k]);

    // 检查是否下载成功
    if(file_exists($config[1])){
    $result[$k] = true;
    }else{
    $result[$k] = false;
    }
    }

    curl_multi_close($mh);

    return $result;

    }

    /**
    * 写入日志
    * @param Array $data 下载文件数据
    * @param Array $flag 下载文件状态数据
    */
    private function to_log($data, $flag){

    // 临时日志数据
    $tmp_log = '';

    foreach($data as $k=>$v){
    $tmp_log .= '['.date('Y-m-d H:i:s').'] url:'.$v[0].' file:'.$v[1].' status:'.$flag[$k].PHP_EOL;
    }

    // 创建日志目录
    if(!is_dir(dirname($this->logfile))){
    mkdir(dirname($this->logfile), 0777, true);
    }

    // 写入日志文件
    file_put_contents($this->logfile, $tmp_log, FILE_APPEND);
    }

    }
    date_default_timezone_set('Asia/Shanghai');
    $base_path = dirname(__FILE__).'/phototest';

    $download_config = array(
    array('http://img.ads.csdn.net/2017/201707141625579530.jpg', $base_path.'/p1.jpg'),
    array('http://geek.csdn.net/assets/images/geek_logo.png', $base_path.'/p2.jpg'),
    array('http://images.csdn.net/20170718/Hans_meitu_401.jpg', $base_path.'/p3.jpg'),
    );

    $obj = new BatchDownLoad($download_config, 2, 10);
    $handle_num = $obj->download();

    echo 'download num:'.$handle_num.PHP_EOL;
    ?>


    </pre>

    ps:经过测试单线程和多线程下载速度是差不多的 因为带宽就这些 这是多线程能更好的使用带宽利用率

  • 相关阅读:
    goweb-goweb基础
    玩转Git
    程序爱好者的常用网站
    高等数学思维导图——6.微分方程
    前端趣玩——超炫的聚光灯效果
    Python课程笔记(四)
    高等数学思维导图——5.多元函数微分法及其应用
    算法很美(四)
    第五章——定积分必记公式
    十大经典排序算法
  • 原文地址:https://www.cnblogs.com/newmiracle/p/11864729.html
Copyright © 2011-2022 走看看