多线程下载类,原生php代码实现,分享给大家。
代码如下:
<?php
/**
* @author 野马
* 多进程下载类
* 主要针对curl的多进程下载进行的封装。
* 使用代码:
<?php
include "multi_download.php";
$xml = file_get_contents('./download.xml');
preg_match_all('/<string>(http.*)</string>/', $xml, $rs);
$md = new multi_download();
foreach( $rs[1] as $line ) {
$filepath = "./file/" . basename($line);
$md->addtask( $line, $filepath );
}
$md->dotask();
?>
*/
class multi_download {
/**
* 下载队列
* @var array
* array(
* array(
* 'handle' => curl resource
* 'filepath' => '/tmp/abc.png'
* 'url' => 'http://www.jb200.com/logo.png'
* 'info' => curl_getinfo
* ),
* )
*/
private $threads = array();
/**
* curl批处理句柄
* @var resource
*/
private $multi_hand = NULL;
/**
* 活动进程指针
* @var array
*/
private $active_points = array();
/**
* 下一个要激活的进程指针
* @var integer
*/
private $active_next = 0;
/**
* 最多活动进程数
* @var integer
*/
private $active_max = 5;
/**
* 模拟浏览器发送agent
*/
private $user_agent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)";
/**
* 构造方法
*/
public function __construct() {
$this->multi_hand = curl_multi_init();
}
/**
* 添加下载任务
* @param string $url 下载地址
* @param string $filepath 文件存放路径,全路径
* @return void
*/
public function addtask( $url, $filepath ) {
$this->threads[] = array(
'handle' => NULL,
'url' => $url,
'filepath' => $filepath,
'info' => array()
);
}
/**
* 执行下载任务
*/
public function dotask() {
while( TRUE ) {
$viewScreen = '';
// 处理每一个进程的状态,清理已完成进程
foreach( $this->active_points as $vk => $point ) {
curl_multi_exec( $this->multi_hand, $active );
$thr = &$this->threads[ $point ];
$thr[ 'info' ] = curl_getinfo( $thr[ 'handle' ] );
// 组织当前进程的回显内容。
$viewScreen .= $this->viewStatus( $thr, $point );
// 下载完成,释放资源
if( $thr[ 'info' ]['http_code'] != 0 && $thr[ 'info' ][ 'size_download' ] == $thr[ 'info' ][ 'download_content_length' ] ) {
curl_multi_remove_handle( $this->multi_hand, $thr[ 'handle' ] );
unset( $this->active_points[ $vk ] );
}
}
// 启动进程
if( $this->active_max - count( $this->active_points ) > 0 ) for(
$i = 0, $num = $this->active_max - count( $this->active_points );
$i < $num && !empty( $this->threads[ $this->active_next ] ) ;
$i++, $this->active_next++
) {
$thr = &$this->threads[ $this->active_next ];
$thr[ 'handle' ] = $this->createconn( $thr[ 'url' ], $thr[ 'filepath' ] );
curl_multi_add_handle ( $this->multi_hand, $thr[ 'handle' ] );
curl_multi_exec( $this->multi_hand, $active );
$this->active_points[] = $this->active_next;
$viewScreen .= $this->viewAddThread( $thr, $this->active_next );
}
// 显示当前状态。
echo `clear`;
echo $viewScreen;
if( empty( $this->threads[ $this->active_next ] ) && empty( $this->active_points ) ) {
echo "rnAll downloaded.rn";
break;
}
// 间歇1秒
sleep( 1 );
}
}
/**
* 格式化进程回显信息。
* @param array $thr 进程数组
* @param ineteger $point 进程ID
* @return string
* @edit www.jb200.com
*/
private function viewStatus( &$thr, $point ) {
if( empty( $thr[ 'info' ] ) ) return false;
$return = "thread({$point}): ";
if( $thr[ 'info' ]['http_code'] == 0 ) {
return $return . "start.rn";
}
elseif( $thr[ 'info' ][ 'size_download' ] == $thr[ 'info' ][ 'download_content_length' ] ) {
$return .= "finish. ";
}
else {
$return .= "active. ";
}
$return .= "[use time:" . intval( $thr[ 'info' ][ 'total_time' ] ) . ",";// ]rn";
$return .= " speed:" . $this->formateSize( $thr[ 'info' ][ 'speed_download' ] ) . ",";
$return .= " download:" . ( intval( $thr[ 'info' ][ 'size_download' ] * 100 / $thr[ 'info' ][ 'download_content_length' ] ) ) . "%(" . $this->formateSize( $thr[ 'info' ][ 'size_download' ] ) . ")";
$return .= " file size:" . $this->formateSize( $thr[ 'info' ][ 'download_content_length' ] );
$return .= "]rn";
return $return;
}
/**
* 格式化进程回显信息。
* @param array $thr 进程数组
* @param ineteger $point 进程ID
* @return string
*/
private function viewAddThread( &$thr, $point ) {
return "thread({$point}): initialize.rn";
}
/**
* 格式化文件大小
* @param integer $size 文件字节数
* @return string
* @edit www.jb200.com
*/
public function formateSize($size) {
$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$unitindex = 0;
while($size > 1024) {
$size /= 1024;
++$unitindex;
}
return sprintf("%0.2f", $size) . $units[ $unitindex ];
}
/**
* 创建curl连接
* @param string $url 下载地址
* @param string $filepath 文件存放路径,全路径
* @return curl resource
*/
public function createconn( $url, $filepath ) {
$fp = fopen ( $filepath, "w" );
$conn = curl_init( $url );
curl_setopt( $conn, CURLOPT_USERAGENT, $this->user_agent );
curl_setopt( $conn, CURLOPT_FILE, $fp );
curl_setopt( $conn, CURLOPT_HEADER, 0 );
curl_setopt( $conn, CURLOPT_CONNECTTIMEOUT, 60 );
return $conn;
}
}
?>