php利用curl实现多进程下载文件类
批量下载文件一般使用循环的方式,逐一执行下载。但在带宽与服务器性能允许的情况下,使用多进程进行下载可以大大提高下载的效率。本文介绍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=""){
$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]);
}
$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);
}
}
?>
demo.php
<?php
require "BatchDownLoad.class.php";
$base_path = dirname(__FILE__)."/photo";
$download_config = array(
array("http://www.example.com/p1.jpg", $base_path."/p1.jpg"),
array("http://www.example.com/p2.jpg", $base_path."/p2.jpg"),
array("http://www.example.com/p3.jpg", $base_path."/p3.jpg"),
array("http://www.example.com/p4.jpg", $base_path."/p4.jpg"),
array("http://www.example.com/p5.jpg", $base_path."/p5.jpg"),
);
$obj = new BatchDownLoad($download_config, 2, 10);
$handle_num = $obj->download();
echo "download num:".$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
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
- 上一篇: 如何查看redis占用内存大小
- 下一篇: nginx优化的一些建议