GrabPic.class.php 5.71 KB
<?php
/**
 * 抓取图片
 */
class Lib_Utils_GrabPic
{
    public static $imageTypes = array('image/jpeg','image/png','image/bmp','image/gif');
    private static $queueLen = 30;
    private static $forksMax = 20;
    private static $urls = array();
    private static $queues = array();
    
    /**
     * 退出队列
     * 
     * @param stream $pic
     * @param array $header
     * @param string $url
     * @return boolean
     */
    public static function queuePop($pic, $header, $url)
    {
        $pid = posix_getpid();
        $offset = array_search($url, self::$queues[$pid]);
        //删除队列
        array_splice(self::$queues[$pid], $offset, 1);
        //图片获取到了
        if(!empty($pic))
        {
            if($header['download_content_length'] != strlen($pic))
            {
            	self::setFailPic($url);
            	return true;
            }
            if(!empty($header) && isset($header['content_type']))
            {
                //不是图片
                if(array_search($header['content_type'], self::$imageTypes) === false)
                {
                    //默认图片
                    $realPath = FRAGMENT_DEFAULT_PIC;
                }
                else
                {
                    $randNumber = sprintf('0%d', rand(1,2));
                    $thumbKey = 'img'.$randNumber;
                    $projectPath = Config_File_Upload::$fragmentimg['path'];
                    $path = Config_File_Image::$imageServer[$thumbKey].$projectPath;
                    $up = new Util_Upload_FileStream($pic, $path);
                    $up->setPrefix($randNumber);
                    $check = $up->write();
                    if(! empty($check['error']) || empty($check['result']['hit']))
                    {
                        return false;
                    }
                    $realPath = $check['result']['hit'][0]['relaPath'];
                    Lib_Images::getImageInfo($realPath, 'fragmentimg');
                    $thumbFormat = Config_File_Upload::$fragmentimgData['format_str'];
                    Lib_Utils_ProcessImage::processThumb($thumbFormat, $thumbKey,  $projectPath, $realPath, 150000);
                }
            }
            else
            {
                //默认图片
                $realPath = FRAGMENT_DEFAULT_PIC;
            }
            //删除队列
            Facade_Common_Queue::delPicQueue($url);
            $urlInfo = self::$urls[$url];
  			self::operation($urlInfo, $realPath);
        }
        else
        {
      		self::setFailPic($url);
        }
    }
    
    /**
     * 设置失败处理
     * 
     * @param string $url
     * @return boolean
     */
    public static function setFailPic($url)
    {
    	$urlInfo = self::$urls[$url];
    	if($urlInfo['fail_times'] > 50)
    	{
    		//删除队列
    		Facade_Common_Queue::delPicQueue($url);
    		self::operation($urlInfo, FRAGMENT_DEFAULT_PIC);
    	}
    	else
    	{
    		Facade_Common_Queue::setPicQueueFailTimes($url, $urlInfo['update_id']);
    	}
    }
    
    /**
     * 进程队列
     * 
     * @param int $pid
     * @return boolean
     */
    public static function forkQueue($pid)
    {
        $times = 0;
        while(count(self::$queues[$pid]) > 0)
        {
            //获取图片,并出列
            Util_Curl::queue(self::$queues[$pid], array('Lib_Utils_GrabPic','queuePop'));
            usleep(100);
            if(($times++) > 3)
            {
                  break;
            }
        }
    }
    
    /**
     * 等待
     * 
     * @param array $pid_arr
     * @param int $num
     */
    public static function wait(&$pid_arr, $num = 0)
    {
        while(count($pid_arr)> $num)
        {
        	$myId = pcntl_waitpid(-1, $status, WNOHANG);
        	foreach($pid_arr as $key => $pid)
        	{
        		if($myId == $pid) unset($pid_arr[$key]);
        	}
        	usleep(100);
        }
    }
    
    /**
     * 操作
     * 
     * @param array $urlInfo
     * @param string $realPath
     * 
     * @return boolean
     */
    public static function operation($urlInfo, $realPath)
    {
    	//商品图片
    	if($urlInfo['type'] == PIC_QUEUE_GOODS_TYPE)
    	{
    		Facade_Fragment_Goods::setGoodsPic($urlInfo['update_id'], $realPath);
    		Facade_Fragment_Fragment::setFragmentPic($urlInfo['update_id'], $realPath);
    	}
    	else if($urlInfo['type'] == PIC_QUEUE_FRAGMENT_TYPE)
    	{
    		Facade_Fragment_Fragment::setFragmentPic($urlInfo['update_id'], $realPath, false);
    		Facade_Fragment_Fragment::setGrabPic(md5($urlInfo['url']), $realPath);
    		usleep(10000);
    	}
    }
    
    /**
     * 运行
     * 
     * @return boolean
     */
    public static function run()
    {
    	$pid_arr = array();
        self::$queues = array();
        self::$urls = Facade_Common_Queue::getPicQueue();
        $len = count(self::$urls);
        $pos = 0;
        $queue = array();
        foreach(self::$urls as $url)
        {
            //进入队列
            array_push($queue, $url['url']);
            if(count($queue) >= self::$queueLen || $pos == ($len - 1 ))
            {
            	self::wait($pid_arr, self::$forksMax);
                $pid = pcntl_fork();
                if ( $pid == -1 )
                {
                    continue;
                }
                else if ($pid) //父进程
                {
                	$pid_arr[] = $pid;
                    $queue = array();
                    $pos = -1;
                }
                else //子进程
                {
                    $pid = posix_getpid();
                    self::$queues[$pid] = $queue;
                    self::forkQueue($pid);
                    die();
                }
            }
            $pos++;
        }
        self::wait($pid_arr);
    }
}