批量下載檔案一般使用迴圈的方式,逐一執行下載。但在頻寬與伺服器效能允許的情況下,使用多進程進行下載可以大大提高下載的效率。本文介紹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
<?phprequire '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
本篇文章講解了批量下載檔案的一些方式,更多相關內容請關注php中文網。