(十)HttpClient以multipart/form-data上傳文件


原文鏈接:https://blog.csdn.net/wsdtq123/article/details/78888734

POST上傳文件

最早的HTTP POST是不支持文件上傳的,給編程開發帶來很多問題。但是在1995年,ietf出台了rfc1867,也就是《RFC 1867 -Form-based File Upload in HTML》,用以支持文件上傳。所以Content-Type的類型擴充了multipart/form-data用以支持向服務器發送二進制數據。因此發送post請求時候,表單<form>屬性enctype共有二個值可選,這個屬性管理的是表單的MIME編碼:
 ①application/x-www-form-urlencoded(默認值)
 ②multipart/form-data
其實form表單在你不寫enctype屬性時,也默認為其添加了enctype屬性值,默認值是enctype="application/x- www-form-urlencoded".

用multipart/form-data上傳文件

今天我們主要談談使用httpclient以multipart/form-data來實現文件上傳。
multipart/form-data的請求頭必須包含一個特殊的頭信息:Content-Type,且其值也必須規定為multipart/form-data,同時還需要規定一個內容分割符用於分割請求體中的多個post的內容,如文件內容和文本內容自然需要分割開來,不然接收方就無法正常解析和還原這個文件了。具體的頭信息如下:Content-Type: multipart/form-data; boundary=${bound}
其中${bound} 是一個占位符,--${bound}代表我們規定的分割符,可以自己任意規定,但為了避免和正常文本重復了,盡量要使用復雜一點的內容,通常由客戶端自主生成,如占位符為:yurnnlukjwfbrdiqvnqnegfitaaddkom,則分隔符為:--yurnnlukjwfbrdiqvnqnegfitaaddkom

一個真實的請求體

一個真實的請求體大致如下:
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="Filename"
 
2.jpg
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="pictitle"
 
2.jpg
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="dir"
 
upload1
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="fileNameFormat"
 
{time}{rand:6}
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="fileName"
 
2.jpg
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="upfile"; filename="2.jpg"
Content-Type: application/octet-stream
 
ÿØÿàJFIFÿÛC		
 
 $.' ",#(7),01444'9=82<.342ÿÛC			
 
2!!22222222222222222222222222222222222222222222222222ÿÀ22"ÿÄÿÄ3!1Aa"Qq¡Á2BR#3¢±ÿÄÿÄ !13QAÿÚ?ÇÛ{çZ3ãçjãêµrÖåcñ÷·µO åÃKë¥Tv®ÊhíI§~2,ºFT4É÷åò©Ëë¹¢Y¼9 etúÍD=ÞØâ¡1Mº	:î~þõStY)vè°l¦t¶
îðâHùË=E>ÿ¤R3µ³/îEæÞb¿¸Í	§\6£O­J#4Ý÷åFÀÕh_E5âw¢§ßg®÷1V¯/­Å·Ô³nDÞ=9ÏÒªi ,xïS^
2Ûx¦ÊF²åÐåHûÒ¬±}K;h×ZóøÂîïÝÐàx®Z4]©
¦àr_Ç-yç½q4Ó2FVÎÀáïåì\Ó¯á×%½6[=Pë9lëÔcJcæ;-²½Ø'ÒPÝÈË5ÉÎ=´©%¶·ÜFc«1%±Û'SL?´íã8¢¶y@zc^]»Tm8·Ss"É1æQwGË'þÔ
Á¢ÊQçYµmÁÐýim<mk9b]ç¡ç^Uðã}MxB8bÛÆk`·ÃÈãw?í\¥º7sÆ¢Ù~i9·&ÞÖÍ #Õ»èF:{Ò6Ûfç¡°à2érj§{âÝðÞâ[	'u×ãD>clä4§
H35ÕÛlÅp4=¥,·(íA~xçO~]êjW
Òªçók­gëæ%¼lª&27ër[áL¤ñÌr7¦II?¹4©`Q^Í,$¤gw9î(¬ÃùÝÆSþTØÿ쯨]?WÞ«¾%b¯C]EVÊÎoþÂ:Ùê¦î,¨>¡Ìw¢Ô0K
7£ô.¬:TÒ${B0ª	
1E¢æUãÉéôïEQ	ÿÙ
--yurnnlukjwfbrdiqvnqnegfitaaddkom
Content-Disposition: form-data; name="Upload"
Submit Query
--yurnnlukjwfbrdiqvnqnegfitaaddkom--
請求體以--yurnnlukjwfbrdiqvnqnegfitaaddkom--結束,其中亂碼部分為上傳的文件流。
HttpClient使用multipart/form-data來上傳文件

封裝的方法:

public static String postFileMultiPart(String url,Map<String,ContentBody> reqParam) throws ClientProtocolException, IOException{
        CloseableHttpClient httpclient = HttpClients.createDefault();
        
        try {
            // 創建httpget.    
            HttpPost httppost = new HttpPost(url);
        	
            //setConnectTimeout:設置連接超時時間,單位毫秒。setConnectionRequestTimeout:設置從connect Manager獲取Connection 超時時間,單位毫秒。這個屬性是新加的屬性,因為目前版本是可以共享連接池的。setSocketTimeout:請求獲取數據的超時時間,單位毫秒。 如果訪問一個接口,多少時間內無法返回數據,就直接放棄此次調用。
            RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000).setSocketTimeout(15000).build();
            httppost.setConfig(defaultRequestConfig);
            
            System.out.println("executing request " + httppost.getURI());
            
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            for(Entry<String,ContentBody> param : reqParam.entrySet()){
            	multipartEntityBuilder.addPart(param.getKey(), param.getValue());
            }
            HttpEntity reqEntity = multipartEntityBuilder.build();
            httppost.setEntity(reqEntity);
            
            // 執行post請求.    
            CloseableHttpResponse response = httpclient.execute(httppost);
            
            System.out.println("got response");
            
            try {  
                // 獲取響應實體    
                HttpEntity entity = response.getEntity();  
                //System.out.println("--------------------------------------");  
                // 打印響應狀態    
                //System.out.println(response.getStatusLine());  
                if (entity != null) { 
                	return EntityUtils.toString(entity,Charset.forName("UTF-8"));
                }
                //System.out.println("------------------------------------");  
            } finally {  
                response.close();
                
            }
        } finally {  
            // 關閉連接,釋放資源    
            try {  
                httpclient.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }
        return null;  
    }

調用postMultipart

String url = "xxxxxxx";
   String httpRes = null;
   String localFileName = "E:/2.jpg";
		
   Map<String,ContentBody> reqParam = new HashMap<String,ContentBody>();
   reqParam.put("Filename", new StringBody(localFileName, ContentType.MULTIPART_FORM_DATA));
   reqParam.put("pictitle", new StringBody(localFileName, ContentType.MULTIPART_FORM_DATA));
   reqParam.put("dir", new StringBody("upload1", ContentType.MULTIPART_FORM_DATA));
   reqParam.put("fileNameFormat", new StringBody("{time}{rand:6}", ContentType.MULTIPART_FORM_DATA));
   reqParam.put("fileName", new StringBody(localFileName, ContentType.MULTIPART_FORM_DATA));
   reqParam.put("fileName", new StringBody(localFileName, ContentType.MULTIPART_FORM_DATA));
   reqParam.put("upfile", new FileBody(new File(fileLocation)));
   reqParam.put("Upload", new StringBody("Submit Query", ContentType.MULTIPART_FORM_DATA));
		
   httpRes = HttpClientUtil.postFileMultiPart(url,reqParam);

  

利用httpclient上傳文件需要兩點:
1.這里一定不能有httppost.addHeader("Content-Type","multipart/form-data; boundary=yurnnlukjwfbrdiqvnqnegfitaaddkom"); 因為這里面有個boundary參數屬性是不可控的。這個值是由瀏覽器生成的。如果強行指明和可能導致邊界值不一致 就會請求失敗 詳細參見 http://blog.csdn.net/xiaojianpitt/article/details/6856536
2.StringBody的ContentType是multipart/form-data
HttpClientUtil工具類
附HttpClientUtil工具類,https://gitee.com/qigugu/dsb-capture-image/blob/master/src/main/java/com/dsb/util/HttpClientUtil.java

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM