最近在開發的一個項目,需要涉及到使用Http請求發送比較大的數據,研究了挺長時間,遇到問題,解決問題,在此分享給大家
1.由於數據量較大,所以采用POST方式 傳輸數據(POST理論上不限制數據大小,但不同服務器都會有相應的默認設置限制數據大小)
2.由於項目需要,使用JSON格式的數據
代碼示例:
JAVA 版,使用Apache的commons-httpClient包 發送http請求,代碼僅供參考,發送請求方式可根據自己需要進行修改
import org.apache.commons.httpclient.*; //使用apache commons httpclient private static final String APPLICATION_JSON = "application/json;charset=uft-8"; private static final String CONTENT_TYPE_TEXT_JSON = "text/json"; /** * 使用http Post 發送json * @param url * @param json 選擇自己喜歡的Json包格式化數據 * @throws Exception */ public static void httpPostWithJSON(String url, String json) throws Exception { // 將JSON進行UTF-8編碼,以便傳輸中文 String encoderJson = URLEncoder.encode(json, "UTF-8"); HttpClient httpclient = new HttpClient(); PostMethod method = new PostMethod(url); RequestEntity requestEntity = new StringRequestEntity(encoderJson); method.setRequestEntity(requestEntity); method.addRequestHeader("Content-Type",APPLICATION_JSON); int result = httpclient.executeMethod(method); System.out.println( "Response status code: " + result); System.out.println( "Response body: " ); System.out.println(method.getResponseBodyAsString()); method.releaseConnection(); }
PHP版,使用curl,這里要注意:curl 使用POST方式發送請求 當數據大於1024字節時,會自動在請求頭加入Expect:100-continue,導致請求掛起,得不到目的服務器的響應.
解決方法:在發送請求前,在請求頭部 手動設置Expect:為空 取消Expect:100-continue 以下是代碼示例:
<?php /** * PHP發送Json對象數據 * * @param $url 請求url * @param $jsonStr 發送的json字符串 * @return array */ function http_post_json($url, $jsonStr) { $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($jsonStr),
'Expect:' ) ); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); return array($httpCode, $response); } $arr = array( 'service' => 's_scenic_info', 'count' => 10 , 'batchNo' => 'JQ201609011230590001', 'flag' => '11111', 'data' => array( array( 'displayName' => '15980851200', 'authenTicket' => '8b11d343d766d4af88d6b8746ec4e786', 'authenUserId' => '1120d8d6ea4a4850b65d0faa40d6dffb', 'timestamp' => '20151009195525' ), array( 'displayName' => '15980851200', 'authenTicket' => '8b11d343d766d4af88d6b8746ec4e786', 'authenUserId' =>'1120d8d6ea4a4850b65d0faa40d6dffb', 'timestamp' => '20151009195525' ) ) ); $url = "http://wangming.hk1.ngrok.cc/tmdata/Dispatcher.do"; $jsonStr = json_encode($arr); echo($jsonStr); list($returnCode, $returnContent) = http_post_json($url, $jsonStr); echo($returnContent) ?>
Expect:100-continue
當使用libcurl的POST方式時,如果POST數據的大小大於1024個字節,libcurl不會直接發送POST請求,而是會分為兩步執行請求:
1、發送一個請求,該請求頭部包含一個Expect: 100-continue的字段,用來詢問server是否願意接受數據
2、當接收到從server返回的100-continue的應答后,它才會真正的發起POST請求,將數據發送給server。
對於“100-continue"這個字段,RFC文檔(http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3)是這么解釋的:它可以讓客戶端在發送請求數據之前去判斷服務器是否願意接收該數據,如果服務器願意接收,客戶端才會真正發送數據,這么做的原因是如果客戶端直接發送請求數據,但是服務器又將該請求拒絕的話,這種行為將帶來很大的資源開銷。所以為了避免這種情況,libcurl在發送大於1024字節的POST請求時采用了這種方法,但是相對的,它會引起請求延遲的加大,另外並不是所有的server都會正確處理並且應答”100-continue“,比如lighttpd,就會返回417”Expectation Failed“,造成請求邏輯出錯。
如果確定服務器不會拒絕1024個字節以上的POST請求,就可以不使用該方法而且也可以避免以上提到的兩個副作用
參考:
http://www.laruence.com/2011/01/20/1840.html