php-curl封装[避免上传文件二义性Bug]
由于php的curl在curl_setopt($curl, CURLOPT_POSTFIELDS, xxx)时, 当xxx为数组时, 如果值的第一个字符是@, 则认为是文件上传, 当同时需要上传文件, 也需要提交可能首字符为@的其他普通数据时, 存在冲突. 因此, 在api_common.php中的post数据的设置进行了封装
<?php/** * php-curl库封装 * author: selfimpr * blog: http://blog.csdn.net/lgg201 * mail: lgg860911@yahoo.com.cn */define('API_CURL_UPLOAD_FILE','__file');#支持的请求方法define('REQUEST_METHOD_GET','GET');define('REQUEST_METHOD_POST','POST');define('REQUEST_METHOD_HEAD','HEAD');#请求行为define('REQUEST_BEHAVIOR_ALLOW_REDIRECT','allow_redirect');define('REQUEST_BEHAVIOR_MAX_REDIRECT','max_redirect');define('REQUEST_BEHAVIOR_USER_AGENT','user_agent');define('REQUEST_BEHAVIOR_AUTOREFERER','autoreferer');define('REQUEST_BEHAVIOR_UPLOAD','upload');define('REQUEST_BEHAVIOR_CONNECTTIMEOUT','connecttimeout');define('REQUEST_BEHAVIOR_DNS_CACHE_TIMEOUT','dns_cache_timeout');define('REQUEST_BEHAVIOR_TIMEOUT','timeout');define('REQUEST_BEHAVIOR_ENCODING','encoding');define('REQUEST_BEHAVIOR_ERROR_HANDLER','error_handler');define('REQUEST_BEHAVIORS','behaviors');$GLOBALS[REQUEST_BEHAVIORS]= array(REQUEST_BEHAVIOR_ALLOW_REDIRECT=> TRUE, REQUEST_BEHAVIOR_MAX_REDIRECT=> 5, REQUEST_BEHAVIOR_USER_AGENT=> 'curl-lib', REQUEST_BEHAVIOR_AUTOREFERER=> TRUE, REQUEST_BEHAVIOR_UPLOAD=> FALSE, REQUEST_BEHAVIOR_CONNECTTIMEOUT=> 3, REQUEST_BEHAVIOR_DNS_CACHE_TIMEOUT=> 3600, REQUEST_BEHAVIOR_TIMEOUT=> 3, REQUEST_BEHAVIOR_ENCODING=> 'gzip', REQUEST_BEHAVIOR_ERROR_HANDLER=> '__default_curl_error_handler', );define('MULTIPART_FORM_DATA_HEAD_FMT','Content-Type: multipart/form-data; boundary=----------------------------%s');define('MULTIPART_FORM_DATA_BODY_STRING',"------------------------------%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n");define('MULTIPART_FORM_DATA_BODY_FILE',"------------------------------%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: application/octet-stream\r\n\r\n%s\r\n");define('MULTIPART_FORM_DATA_BODY_END',"------------------------------%s--\r\n\r\n");#响应键值define('RESP_CODE','resp_code');define('RESP_BODY','resp_body');define('RESP_HEADER','resp_header');#HTTP 1xx状态验证define('HTTP_1XX_RESP','/^HTTP\/1.[01] 1\d{2} \w+/');#默认错误处理的错误消息define('E_CURL_ERROR_FMT','curl "%s" error[%d]: %s');#默认的curl错误处理function __default_curl_error_handler($curl, $url, $errno, $errstr) {trigger_error(sprintf(E_CURL_ERROR_FMT, $url, $errno, $errstr), E_USER_ERROR);}#切换CURL请求方法function __method_switch($curl, $method) {switch ( $method) {case REQUEST_METHOD_POST:__curl_setopt($curl, CURLOPT_POST, TRUE);break;case REQUEST_METHOD_HEAD:__curl_setopt($curl, CURLOPT_NOBODY, TRUE);break;case REQUEST_METHOD_GET:__curl_setopt($curl, CURLOPT_HTTPGET, TRUE);break;default:break;}}#设置默认头信息function __default_header_set($curl) {__curl_setopt($curl, CURLOPT_RETURNTRANSFER,TRUE);__curl_setopt($curl, CURLOPT_HEADER,TRUE);__curl_setopt($curl, CURLOPT_FOLLOWLOCATION,(bool)curl_behavior(REQUEST_BEHAVIOR_ALLOW_REDIRECT));__curl_setopt($curl, CURLOPT_MAXREDIRS,(int)curl_behavior(REQUEST_BEHAVIOR_MAX_REDIRECT));__curl_setopt($curl, CURLOPT_USERAGENT,(string)curl_behavior(REQUEST_BEHAVIOR_USER_AGENT));__curl_setopt($curl, CURLOPT_AUTOREFERER,(bool)curl_behavior(REQUEST_BEHAVIOR_AUTOREFERER));__curl_setopt($curl, CURLOPT_UPLOAD,(bool)curl_behavior(REQUEST_BEHAVIOR_UPLOAD));__curl_setopt($curl, CURLOPT_CONNECTTIMEOUT,(int)curl_behavior(REQUEST_BEHAVIOR_CONNECTTIMEOUT));__curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT,(int)curl_behavior(REQUEST_BEHAVIOR_DNS_CACHE_TIMEOUT));__curl_setopt($curl, CURLOPT_TIMEOUT,(int)curl_behavior(REQUEST_BEHAVIOR_TIMEOUT));__curl_setopt($curl, CURLOPT_ENCODING,(string)curl_behavior(REQUEST_BEHAVIOR_ENCODING));}#设置用户自定义头信息function __custom_header_set($curl, $headers = NULL) {if ( empty($headers) ) return ;if ( is_string($headers) ) $headers= explode("\r\n", $headers);#类型修复foreach ( $headers as &$header ) if ( is_array($header) ) $header= sprintf('%s: %s', $header[0], $header[1]);__curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);}#设置请求bodyfunction __datas_set($curl, $datas = NULL) {if ( empty($datas) ) return ;if ( is_array($datas) ) {$custom_body= FALSE;$uniqid= uniqid();$custom_body_str= '';foreach ( $datas as $name => $data ) {if ( is_array($data) && array_key_exists(API_CURL_UPLOAD_FILE, $data) ) {$file= $data[API_CURL_UPLOAD_FILE];if ( file_exists($file) ) {$custom_body= TRUE;$custom_body_str.= sprintf(MULTIPART_FORM_DATA_BODY_FILE, $uniqid, $name, $file, file_get_contents($file));}} else {$custom_body_str.= sprintf(MULTIPART_FORM_DATA_BODY_STRING, $uniqid, $name, $data);}}if ( $custom_body ) {curl_setopt($curl, CURLOPT_HTTPHEADER, array(sprintf(MULTIPART_FORM_DATA_HEAD_FMT, $uniqid)));$datas= $custom_body_str . sprintf(MULTIPART_FORM_DATA_BODY_END, $uniqid);}}__curl_setopt($curl, CURLOPT_POSTFIELDS, $datas);}#对curl_setopt的封装function __curl_setopt($curl, $optname, $optval) {curl_setopt($curl, $optname, $optval);__curl_error($curl);}#curl错误检查处理function __curl_error($curl) {if ( curl_errno($curl) ) {$url= curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);$errno= curl_errno($curl);$errstr= curl_error($curl);$errh= curl_behavior(REQUEST_BEHAVIOR_ERROR_HANDLER);if ( function_exists($errh) )$errh($curl, $url, $errno, $errstr);}}#api默认行为切换function curl_behavior($names, $values = NULL) {if ( !is_string($names) && !is_array($names) ) return ;if ( !is_null($values) ) {if ( is_string($names) ) $GLOBALS[REQUEST_BEHAVIORS][$names]= $values;else if ( is_array($names) && !is_array($values) )foreach ( $names as $name )$GLOBALS[REQUEST_BEHAVIORS][$name]= $values;else if ( is_array($names) && is_array($values) )foreach ( $names as $k => $name ) $GLOBALS[REQUEST_BEHAVIORS][$name]= $values[$k];}if ( is_string($names) ) {$return= $GLOBALS[REQUEST_BEHAVIORS][$names];} else if ( is_array($names) ) {$return= array();foreach ( $names as $name ) $return[$name]= array_key_exists($name, $GLOBALS[REQUEST_BEHAVIORS]) ? $GLOBALS[REQUEST_BEHAVIORS][$name]: NULL;}return $return;}#请求入口function curl_request($url, $method, $datas = NULL, $headers = NULL) {$curl= curl_init($url);__method_switch($curl, $method);__default_header_set($curl);__custom_header_set($curl, $headers);__datas_set($curl, $datas);$response= curl_exec($curl);__curl_error($curl);$status_code= curl_getinfo($curl, CURLINFO_HTTP_CODE);$components= explode("\r\n\r\n", $response);$i= -1;while ( ++ $i < count($components) ) if ( !preg_match(HTTP_1XX_RESP, $components[$i]) ) break;$headers= $components[$i];$body= implode("\r\n\r\n", array_slice($components, $i + 1));return array(RESP_CODE=> $status_code, RESP_HEADER=> $headers, RESP_BODY=> $body, );}#GET请求function curl_get($url, $headers = NULL) {return curl_request($url, REQUEST_METHOD_GET, NULL, $headers);}#POST请求function curl_post($url, $datas = NULL, $headers = NULL) {return curl_request($url, REQUEST_METHOD_POST, $datas, $headers);}#HEAD请求function curl_head($url, $headers = NULL) {return curl_request($url, REQUEST_METHOD_HEAD, NULL, $headers);}#构造上传文件字段function curl_post_file($file) {return array(API_CURL_UPLOAD_FILE=> $file, );}#读取响应码function curl_resp_code($resp) {return $resp[RESP_CODE];}#读取响应头function curl_resp_header($resp) {return $resp[RESP_HEADER];}#读取响应体function curl_resp_body($resp) {return $resp[RESP_BODY];}