1.CURL方式發送數據及上傳文件
1 <?php 2 3 class IndexController extends ControllerBase 4 { 5 6 public function indexAction() 7 { 8 $url = 'http://192.168.10.168/home/index'; 9 $data = array( 10 'name'=>'網絡開發', 11 'address'=>'123456789', 12 //"file" => "@".getcwd()."/temp/test.zip",//要上傳的本地文件地址"@"上傳時候,上傳路徑前面要有@符號 13 'file' => new cURLFile(getcwd()."/temp/test.zip"), 14 ); 15 16 //沒有影響,但是還是有少部分服務器不兼容。本文得出的結論是,在沒有需要上傳文件的 17 //情況下,盡量對post提交的數據進行http_build_query,然后發送出去,能實現更好的兼容性, 18 $url = $url."?".http_build_query($data); $res = $this->mycurl($url); 19 20 //解析xml 21 //simplexml_load_string($pageContents, 'SimpleXMLElement', LIBXML_NOCDATA) 22 //$data = json_encode($data); 23 //$res = $this->mycurl($url,$data); 24 var_export($res); 25 } 26 public function mycurl($url, $postfields = NULL, $method='POST'){ 27 //$url = "http://127.0.0.1:8888"; 28 $result = array( 'header' => '', 29 'body' => '', 30 'curl_error' => '', 31 'http_code' => '', 32 'last_url' => ''); 33 $timeout = 10;//超時時間 34 $connectTimeout = 0;//無限等待 35 $ssl = substr($url, 0, 8) == "https://" ? true : false; 36 $header = array( 37 //"Content-Type: application/x-www-form-urlencoded", 38 "Content-Type: multipart/form-data", 39 "Keep-Alive: 300"); 40 41 //開始curl 42 $ci = curl_init(); 43 //設置curl使用的HTTP協議,CURL_HTTP_VERSION_NONE(讓curl自己判斷),CURL_HTTP_VERSION_1_0(HTTP/1.0),CURL_HTTP_VERSION_1_1(HTTP/1.1) 44 curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 45 //在HTTP請求中包含一個”user-agent”頭的字符串。 46 curl_setopt($ci, CURLOPT_USERAGENT,$_SERVER['HTTP_USER_AGENT']); 47 curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $connectTimeout); //在發起連接前等待的時間,如果設置為0,則無限等待 48 curl_setopt($ci, CURLOPT_TIMEOUT, $timeout); 49 //如果成功只返回TRUE,自動輸出返回的內容。如果失敗返回FALSE 獲取的信息以文件流的形式返回 50 curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE); 51 curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1); // 使用自動跳轉 52 curl_setopt($ci, CURLOPT_AUTOREFERER, 1); // 自動設置Referer 53 //header中“Accept-Encoding: ”部分的內容,支持的編碼格式為:"identity","deflate","gzip"。如果設置為空字符串,則表示支持所有的編碼格式 54 curl_setopt($ci, CURLOPT_ENCODING, ""); 55 if ($ssl) { 56 curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, 0); // 信任任何證書 瀏覽器訪問https的時候,瀏覽器會自動加載網站的安全證書進行加密 57 curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, 1); // 檢查證書中是否設置域名 從證書中檢查SSL加密算法是否存在 58 } 59 //避免data數據過長問題 設置一個header中傳輸內容的數組 60 curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:')); 61 62 //以json方式傳輸 63 if(!is_array($postfields) && is_string($postfields)){ 64 curl_setopt($ci, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Content-Length:'.strlen($postfields))); 65 } 66 67 //已指定header頭格式傳輸 68 //curl_setopt($ci, CURLOPT_HTTPHEADER, $header); 69 //設置一個回調函數,這個函數有兩個參數,第一個是curl的資源句柄,第二個是輸出的header數據。header數據的輸出必須依賴這個函數,返回已寫入的數據大小 70 //如果你想把一個頭包含在輸出中,設置這個選項為一個非零值。 返回response頭部信息 顯示返回的Header區域內容 71 curl_setopt($ci, CURLOPT_HEADER, 1); 72 73 switch ($method) { 74 case 'POST': 75 curl_setopt($ci, CURLOPT_POST, 1);// 發送一個常規的Post請求 76 if (!empty($postfields)) { 77 curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields); 78 } 79 break; 80 case 'DELETE': 81 curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE'); 82 if (!empty($postfields)) { 83 $url = "{$url}?{$postfields}"; 84 } 85 break; 86 } 87 curl_setopt($ci, CURLOPT_URL, $url); 88 //發送請求的字符串頭 89 curl_setopt($ci, CURLINFO_HEADER_OUT, TRUE); 90 91 $response = curl_exec($ci); 92 $error = curl_error($ci); 93 94 //獲取http頭部信息 95 $response_header_info = curl_getinfo($ci, CURLINFO_HEADER_OUT);// CURLINFO_HEADER_OUT 必須設置成1 才返回 96 $http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE); 97 $result['http_code'] = $http_code; 98 $result['last_url'] = curl_getinfo($ci,CURLINFO_EFFECTIVE_URL); 99 $this->log->info("response_header_info:\n".$response_header_info); 100 101 //獲取錯誤信息 102 if ( $error != "" ) 103 { 104 $this->log->info("狀態碼:".$http_code." 發送失敗:".json_encode($error)); 105 $result['curl_error'] = $error; 106 $result['curl_error_no'] = curl_errno($ci); 107 curl_close ($ci); 108 return $result; 109 } 110 if( $response ) 111 { 112 $header_size = curl_getinfo($ci,CURLINFO_HEADER_SIZE); 113 $result['header'] = substr($response, 0, $header_size); 114 $result['body'] = substr( $response, $header_size ); 115 $this->log->info("狀態碼:".$http_code." 成功發送:".json_encode($response)); 116 } 117 curl_close ($ci); 118 return $result; 119 120 } 121 122 }
接受方PHP:receive.php
1 <?php 2 3 class HomeController extends ControllerBase 4 { 5 6 public function indexAction() 7 { 8 9 echo "Success ok!"; 10 if($_GET){ 11 foreach ($_GET as $k =>$v) 12 { 13 $this->log->debug("get----------------$k=$v"); 14 } 15 } 16 //只能接收Content-Type: application/x-www-form-urlencoded提交的數據 17 if($_POST){ 18 foreach ($_POST as $k =>$v) 19 { 20 $this->log->debug("post----------------$k=$v"); 21 } 22 } 23 //方法2、file_get_contents("php://input"); Content-Type: application/json 24 $input = file_get_contents("php://input"); 25 if($input){ 26 $json_data = json_decode($input); 27 if($json_data){ 28 foreach ($json_data as $k =>$v) 29 { 30 $this->log->debug("json_decode----------------$k=$v"); 31 } 32 } 33 $this->log->debug("file_get----------------$input"); 34 } 35 //獲取上傳文件 36 if($_FILES){ 37 $file = move_uploaded_file($_FILES['file']['tmp_name'], getcwd()."/files/1.rar"); 38 if($file){ 39 echo "保存文件成功"; 40 } 41 } 42 43 } 44 }
2.stream流的方式
stream_context_create — 創建資源流上下文
stream_context_create 作用:創建並返回一個文本數據流並應用各種選項,
可用於 fopen(), file_get_contents() 等過程的超時設置、代理服務器、請求方式、頭信息設置的特殊過程。
例子:
<?php function post($url, $data) { $postdata = http_build_query( $data ); $opts = array('http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata ) ); $context = stream_context_create($opts); $result = file_get_contents($url, false, $context); return $result; }
3.socket方式
使用套接字建立連接,拼接 HTTP 報文發送數據進行 HTTP 請求。
fsockopen — 打開一個網絡連接或者一個Unix套接字連接
說明
$hostname
[, int $port
= -1 [, int &$errno
[, string &$errstr
[, float $timeout
= ini_get("default_socket_timeout") ]]]] )
初始化一個套接字連接到指定主機(hostname
)。
PHP支持以下的套接字傳輸器類型列表 所支持的套接字傳輸器(Socket Transports)列表。也可以通過stream_get_transports()來獲取套接字傳輸器支持類型。
默認情況下將以阻塞模式開啟套接字連接。當然你可以通過stream_set_blocking()將它轉換到非阻塞模式。
stream_socket_client()與之非常相似,而且提供了更加豐富的參數設置,包括非阻塞模式和提供上下文的的設置。
參數
-
hostname
-
如果安裝了OpenSSL,那么你也許應該在你的主機名地址前面添加訪問協議ssl://或者是tls://,從而可以使用基於TCP/IP協議的SSL或者TLS的客戶端連接到遠程主機。
-
port
-
端口號。如果對該參數傳一個-1,則表示不使用端口,例如unix://。
-
errno
-
如果傳入了該參數,holds the system level error number that occurred in the system-level connect() call。
如果
errno
的返回值為0,而且這個函數的返回值為FALSE
,那么這表明該錯誤發生在套接字連接(connect())調用之前,導致連接失敗的原因最大的可能是初始化套接字的時候發生了錯誤。 -
errstr
-
錯誤信息將以字符串的信息返回。
-
timeout
-
設置連接的時限,單位為秒。
Note:
注意:如果你要對建立在套接字基礎上的讀寫操作設置操作時間設置連接時限,請使用stream_set_timeout(),fsockopen()的連接時限(
timeout
)的參數僅僅在套接字連接的時候生效。
返回值
fsockopen()將返回一個文件句柄,之后可以被其他文件類函數調用(例如:fgets(),fgetss(),fwrite(),fclose()還有feof())。如果調用失敗,將返回FALSE
。
<?php $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "GET / HTTP/1.1\r\n"; $out .= "Host: www.example.com\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } ?>
用fsockopen 以post方式獲取數據
1 <?php 2 function HTTP_Post($URL,$data,$cookie, $referrer="") 3 { 4 // parsing the given URL 5 $URL_Info=parse_url($URL); 6 // Building referrer 7 if($referrer=="") // if not given use this script as referrer 8 $referrer="111"; 9 // making string from $data 10 foreach($data as $key=>$value) 11 $values[]="$key=".urlencode($value); 12 $data_string=implode("&",$values); 13 // Find out which port is needed - if not given use standard (=80) 14 if(!isset($URL_Info["port"])) 15 $URL_Info["port"]=80; 16 // building POST-request: 17 $request.="POST ".$URL_Info["path"]." HTTP/1.1\n"; 18 $request.="Host: ".$URL_Info["host"]."\n"; 19 $request.="Referer: $referer\n"; 20 $request.="Content-type: application/x-www-form-urlencoded\n"; 21 $request.="Content-length: ".strlen($data_string)."\n"; 22 $request.="Connection: close\n"; 23 $request.="Cookie: $cookie\n"; 24 $request.="\n"; 25 $request.=$data_string."\n"; 26 $fp = fsockopen($URL_Info["host"],$URL_Info["port"]); 27 fputs($fp, $request); 28 while(!feof($fp)) { 29 $result .= fgets($fp, 1024); 30 } 31 fclose($fp); 32 return $result; 33 } 34 ?>
用fsockopen函數打開url,以get方式獲取完整的數據,包括header和body,fsockopen需要 PHP.ini 中
allow_url_fopen 選項開啟
1 <?php 2 function get_url ($url,$cookie=false) 3 { 4 $url = parse_url($url); 5 $query = $url[path]."?".$url[query]; 6 echo "Query:".$query; 7 $fp = fsockopen( $url[host], $url[port]?$url[port]:80 , $errno, $errstr, 30); 8 if (!$fp) { 9 return false; 10 } else { 11 $request = "GET $query HTTP/1.1\r\n"; 12 $request .= "Host: $url[host]\r\n"; 13 $request .= "Connection: Close\r\n"; 14 if($cookie) $request.="Cookie: $cookie\n"; 15 $request.="\r\n"; 16 fwrite($fp,$request); 17 while()) { 18 $result .= @fgets($fp, 1024); 19 } 20 fclose($fp); 21 return $result; 22 } 23 } 24 //獲取url的html部分,去掉header 25 function GetUrlHTML($url,$cookie=false) 26 { 27 $rowdata = get_url($url,$cookie); 28 if($rowdata) 29 { 30 $body= stristr($rowdata,"\r\n\r\n"); 31 $body=substr($body,4,strlen($body)); 32 return $body; 33 } 34 return false; 35 } 36 ?>