Rumah  >  Artikel  >  pembangunan bahagian belakang  >  如何利用phpcurl实现多进程下载文件类

如何利用phpcurl实现多进程下载文件类

jacklove
jackloveasal
2018-06-08 16:55:332645semak imbas

批量下载文件一般使用循环的方式,逐一执行下载。但在带宽与服务器性能允许的情况下,使用多进程进行下载可以大大提高下载的效率。本文介绍php利用curl的多进程请求方法,实现多进程同时下载文件。

原理:

使用curl的批处理方法,开启多进程,实现批量下载文件。

主要方法:

curl_multi_init
返回一个新cURL批处理句柄

curl_multi_add_handle
向curl批处理会话中添加单独的curl句柄

curl_multi_exec
运行当前 cURL 句柄的子连接

curl_multi_getcontent
如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流

curl_multi_remove_handle
移除curl批处理句柄资源中的某个句柄资源

curl_multi_close
关闭一组cURL句柄

完整代码如下:

BatchDownLoad.class.php

<?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=&#39;&#39;){
        $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__).&#39;/batch_download_&#39;.date(&#39;Ymd&#39;).&#39;.log&#39;;
        }
    }    /**
     * 执行下载
     * @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], &#39;a&#39;);

            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, &#39;Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)&#39;);            // 加入处理
            curl_multi_add_handle($mh, $ch[$k]);
        }        $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 = &#39;&#39;;        foreach($data as $k=>$v){            $tmp_log .= &#39;[&#39;.date(&#39;Y-m-d H:i:s&#39;).&#39;] url:&#39;.$v[0].&#39; file:&#39;.$v[1].&#39; status:&#39;.$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);
    }

}?>

demo.php

<?phprequire &#39;BatchDownLoad.class.php&#39;;$base_path = dirname(__FILE__).&#39;/photo&#39;;$download_config = array(    array(&#39;http://www.example.com/p1.jpg&#39;, $base_path.&#39;/p1.jpg&#39;),    array(&#39;http://www.example.com/p2.jpg&#39;, $base_path.&#39;/p2.jpg&#39;),    array(&#39;http://www.example.com/p3.jpg&#39;, $base_path.&#39;/p3.jpg&#39;),    array(&#39;http://www.example.com/p4.jpg&#39;, $base_path.&#39;/p4.jpg&#39;),    array(&#39;http://www.example.com/p5.jpg&#39;, $base_path.&#39;/p5.jpg&#39;),
);$obj = new BatchDownLoad($download_config, 2, 10);$handle_num = $obj->download();echo &#39;download num:&#39;.$handle_num.PHP_EOL;?>

执行后日志输出

[2017-07-16 18:04:21] url:http://www.example.com/p1.jpg file:/home/fdipzone/photo/p1.jpg status:1[2017-07-16 18:04:21] url:http://www.example.com/p2.jpg file:/home/fdipzone/photo/p2.jpg status:1[2017-07-16 18:04:21] url:http://www.example.com/p3.jpg file:/home/fdipzone/photo/p3.jpg status:1[2017-07-16 18:04:21] url:http://www.example.com/p4.jpg file:/home/fdipzone/photo/p4.jpg status:1[2017-07-16 18:04:21] url:http://www.example.com/p5.jpg file:/home/fdipzone/photo/p5.jpg status:1

本篇文章讲解了批量下载文件的一些方式,更多相关内容请关注php中文网。

相关推荐:

如何通过php判断本地及远程文件是否存在

关于mysql表数据行列转换方法的讲解

关于php 日志类的讲解

Atas ialah kandungan terperinci 如何利用phpcurl实现多进程下载文件类. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn