C语言 c++ php mysql nginx linux lnmp lamp lanmp memcache redis 面试 笔记 ppt 设计模式 问题 远程连接

小文件存储组件

 

<?php
/**
 * 小文件存储组件
 *
 */
class SmallFileStorage 
{
    /**
     * 服务器配置信息
     * @var array{
     * 'host'=>'...'
     * 'port'=>...
     * }
     */
    public $serverConfig = array('host'=>'10.130.84.211','port'=>13000);

    /**
     * http get请求
     * @param string $cgiPath
     * @return 返回正文
     */
    private function httpGet($cgiPath)
    {
        $fp = @fsockopen($this->serverConfig['host'], $this->serverConfig['port'], $errno, $errstr, 3);
        if($fp === false) {
            print('connect time out error');
            return false;   
        }

        stream_set_timeout($fp,1); //设置超时为1s
        $ret = @fwrite($fp,"GET $cgiPath HTTP/1.0\r\n\r\n");
        if($ret === false) {
            print('write error');
            return false;
        }

        $response_data = @fread($fp,512);
        $OKSTR = '200 OK';
        $okPos = stripos($response_data,$OKSTR);
        if($okPos !== false) {
            var_dump($response_data);
            //暂且假设第一次读取就能读到Content-Length
            //TODO
            $CLSTR = 'Content-Length:';
            $clPos = stripos($response_data,$CLSTR,$okPos+strlen($OKSTR));
            if($clPos === false) return false;
            $clEndPos = strpos($response_data,"\r\n",$clPos+strlen($CLSTR));
            if($clEndPos === false) return false;

            $contentLen = intval(substr($response_data,$clPos+strlen($CLSTR),$clEndPos-$clPos-strlen($CLSTR)));
            //长度不应该为0
            if($contentLen <= 0) return false;

            //获取正文内容
            $pattern_str = "\r\n\r\n";
            $pattern_pos = strrpos($response_data,$pattern_str);
            if($pattern_pos !== false) {
                $partData = substr($response_data,$pattern_pos+strlen($pattern_str));
                while(strlen($partData) < $contentLen) {
                    $response_data = @fread($fp,$contentLen-strlen($partData));
                    if(empty($response_data)) return false;
                    $partData .= $response_data;
                }
                return $partData;
            }
        }

        print('read unexpected error');
        return false;
    }

    /**
     * http 上传文件,以字符串形式上传
     * 由于小文件上传为异部操作,并且提前做了分享,所以必需保证数据处理可靠,必要情况下要重试
     * @param string $cgiPath
     * @param $data string 上传内容
     * @return bool
     */
    private function httpPostFile($data,$cgiPath)
    {
        $fp = @fsockopen($this->serverConfig['host'], $this->serverConfig['port'], $errno, $errstr, 3);
        if($fp === false) {
            print('connect time out error');
            return false;   
        }
        stream_set_timeout($fp,1); //设置超时为1s

        //一次性写入
        $line_1 = "POST $cgiPath HTTP/1.0\r\n";
        $line_2 = "Content-Type: application/x-www-form-urlencoded\r\n";
        $line_3 = "Content-length: ".strlen($data)."\r\n\r\n";
        $ret = @fwrite($fp,$line_1.$line_2.$line_3);
        if($ret === false) {
            print('write error');
            return false;   
        }

        //数据量比较大,一次写不完
        for($written = 0; $written < strlen($data); $written += $fwrite) {
            $fwrite = fwrite($fp, substr($data, $written));
            if ($fwrite === false) {
                print('write error');
                return false;   
            }
            if ($fwrite === 0) {
               break;   
            }
        }

        $response_data = @fread($fp, 32);
        if(empty($response_data)) {
            print('read error');
            return false;   
        }
        fclose($fp);
        //解析返回码
        return stripos($response_data,'200 OK') === false ? false : true;

    }
    
    /**
     * 文件夹创建
     * @param $info array(
     * 'buid'=>,
     * 'uin'=>,
     * 'dir_path'=>,
     * 'name'=>,
     * )
     */
    public function dirCreate($info)
    {
        $cgiName = '/store_dir_create?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
    /*
     *删除一个目录
     *@param $info array(
     * 'buid'=>,
     * 'uin'=>,
     * 'dir_path'=>
     * )
     */
    public function dirDelete($info)
    {
        $cgiName = '/store_dir_delete?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
    /*
     *删除一个目录
     *@param $info array(
     * 'buid'=>,
     * 'uin'=>,
     * 'dir_path'=>
     * )
     */
    public function dirList($info)
    {
        $cgiName = '/store_dir_list?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
    
    /**
     * 小文件内网上传,为性能考虑,文件夹提前手动建好
     * @param $data 文件内容
     * @param $info array(
     * 'buid'=>,
     * 'uin'=>,
     * 'dir_path'=>,
     * 'name'=>,
     * 'fsize'=>,
     * 'offset'=>,
     * )
     */
    public function fileUpload($data,$info)
    {
        $cgiName = '/store_file_upload?';
        $cgiPath = $cgiName.http_build_query($info);
        return $this->httpPostFile($data,$cgiPath);
    }
    /*
     *删除一个文件
     *@param $info array(
     * 'buid'=>,
     * 'uin'=>,
     * 'dir_path'=>,
     * 'name'=>,
     * )
     */
    public function fileDelete($info)
    {
        $cgiName = '/store_file_delete?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
    /*
     *查询文件是上传的状态
     *@param $info array(
     * 'buid'=>,
     * 'uin'=>,
     * 'dir_path'=>,
     * 'name'=>,
     * )
     */
    public function fileQuery($info)
    {
        $cgiName = '/store_file_query?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
    /*
     *下载指定的文件
     *@param $info array(
     * 'buid'=>,
     * 'uin'=>,
     * 'dir_path'=>,
     * 'name'=>,
     * 'offset'=>,
     * 'length'=>
     * )
     */
    public function fileDownload($info)
    {
        $cgiName = '/store_file_download?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
    
     /**
     * 小文件外网下载
     * @param $info array(
     * 'buid'=>,
     * 'uin'=>,
     * 'dir_path'=>,
     * 'name'=>,
     * 'time'=>,
     * )
     * @return string 文件跳转url
     */
    public function fileOuterDownload($info)
    {
        //生成外网key
        //
        $cgiName = '/store_get_key?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        if($response_code === false) {
            return false;   
        }
        
        //多带了一个time参数,不要紧
        $preUrl = 'http://szmain.fcloud.store.qq.com/store_file_download?'.http_build_query($info).'&key='.$response_code;
        return $preUrl;
    }
    
    /*
     *以下函数为raw系列的函数,主要针对不需要uin上传和下载的场景
     */
     
    /*
     *fileRawUpload($array,&$uuid)
     *@param $data;
     *@param array(
     *    buid=>'',
     *    filename=>'',
     *    fsize=>'',
     *    offset=>''
     *)
     *@return string httpretcode;
     */
     public function fileRawUpload($data,$info,&$uuid)
    {
        $cgiName = '/store_raw_upload?';
        $uuid = md5($info['filename']."".time());
        $info['uuid'] =  $uuid;
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpPostFile($data,$cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
    
    /**
     * 小文件内网下载
     * @param $info array(
     * 'buid'=>,
     * 'uuid'=>,
     * 'name'=>,
     * 'time'=>,
     * 'ip'=>
     * )
     * @return string 文件跳转url
     */
    public function fileInnerRawDownload($info)
    {
        //生成外网key
        //
        $cgiName = '/store_raw_download?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        return $response_code;
    }
    
    /**
     * 小文件外网下载
     * @param $info array(
     * 'buid'=>,
     * 'uuid'=>,
     * 'name'=>,
     * 'time'=>,
     * 'ip'=>
     * )
     * @return string 文件跳转url
     */
    public function fileOuterRawDownload($info)
    {
        //生成外网key
        //
        $cgiName = '/store_get_key?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        if($response_code === false) {
            return false;   
        }
        
        //多带了一个time参数,不要紧
        $preUrl = 'http://szmain.fcloud.store.qq.com/store_raw_download?'.http_build_query($info).'&key='.$response_code;
        return $preUrl;
    }
    
    /**
     * 小文件查询
     * @param $info array(
     * 'buid'=>,
     * 'uuid'=>
     * )
     * @return string http返回码
     */
    public function fileRawQuery($info)
    {
        //生成外网key
        //
        $cgiName = '/store_raw_query?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
    
    /**
     * 小文件删除
     * @param $info array(
     * 'buid'=>,
     * 'uuid'=>
     * )
     * @return string http返回码
     */
    public function fileRawDelete($info)
    {
        //生成外网key
        //
        $cgiName = '/store_raw_delete?';
        $cgiPath = $cgiName.http_build_query($info);
        $response_code = $this->httpGet($cgiPath);
        //TODO
        //解析返回码
        return $response_code;
    }
}

 

posted on 2014-08-31 17:23  思齐_  阅读(866)  评论(2编辑  收藏  举报