小文件存储组件
<?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; } }