C#記一次http協(xié)議multipart/form-data的boundary問(wèn)題
1.問(wèn)題描述
使用post方法調(diào)用上級(jí)聯(lián)網(wǎng)廠(chǎng)家接口,返回http狀態(tài)碼415,返回信息Content type ‘application/x-www-form-urlencoded’ not supported
測(cè)試上級(jí)聯(lián)網(wǎng)廠(chǎng)家接口使用的是Postman工具,工具下載地址:https://www.getpostman.com/downloads/
使用application/x-www-form-urlencoded調(diào)用接口,返回http狀態(tài)碼415,如圖:
既然服務(wù)器無(wú)法處理請(qǐng)求附帶的媒體格式,那么改用multipart/form-data試試?
測(cè)試后發(fā)現(xiàn)可以調(diào)用成功,如圖:
我們都知道ContentType為application/x-www-form-urlencoded的請(qǐng)求頭、體如何構(gòu)造,如:
HttpWebRequest request = WebRequest.Create(new Uri(url)) as HttpWebRequest; request.Method = "POST"; request.Host = Properties.Settings.Default.IP; request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8"; request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko"; request.Accept = "*/*"; request.CookieContainer = cc; request.KeepAlive = true; string postData = string.Format("action=cx&hphm={0}&hpzl=&jclb=&detlsh=&clpp=&clxh=&rlzl=&pfbz=&jcff=&evl=&staName={1}&detLineId=&syxz=&rqyi={2}&rqer={3}&RQXZ=JCRQ&CXJL=Jiance&cllb=&clgs=&zcrq=&zzl=&clsbdh=&syr=&ccdjrq=&page={4}&rows=10", hphm, staName, rqyi, rqer, page); byte[] postdatabyte = Encoding.GetEncoding("utf-8").GetBytes(postData); request.ContentLength = postdatabyte.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(postdatabyte, 0, postdatabyte.Length); } HttpWebResponse response = request.GetResponse() as HttpWebResponse; using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8"))) { string temp = reader.ReadToEnd(); }
但是!multipart/form-data的請(qǐng)求頭與請(qǐng)求體該如何構(gòu)造呢?像下面這樣?
string url = "http://112.17.158.12:8180/intf/services/query"; HttpWebRequest request = WebRequest.Create(new Uri(url)) as HttpWebRequest; request.Method = "POST"; request.Host = "112.17.158.12:8180"; request.ContentType = "multipart/form-data; "; request.UserAgent = "PostmanRuntime/7.17.1"; request.Accept = "*/*"; request.KeepAlive = true; string postData = @"jkuser=33088102&jkpasswd=33088102&jsondata={""jkid"":""R10"",""requestTime"":""20190919110603"",""body"":[{""inspstationcode"":""33088102""}]}"; byte[] postdatabyte = Encoding.GetEncoding("utf-8").GetBytes(postData); request.ContentLength = postdatabyte.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(postdatabyte, 0, postdatabyte.Length); } HttpWebResponse response = request.GetResponse() as HttpWebResponse; using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8"))) { string temp = reader.ReadToEnd(); }
顯然不對(duì),捕獲到了"遠(yuǎn)程服務(wù)器返回錯(cuò)誤:(500)內(nèi)部服務(wù)器錯(cuò)誤。"異常,那么我們?cè)撛趺崔k呢?
2.解決思路
既然Postman工具使用ContentType為multipart/form-data類(lèi)型post數(shù)據(jù)可以成功,那么我們寫(xiě)的C#程序應(yīng)該也可以呀!那怎么辦呢?。。。。沒(méi)錯(cuò)??!就是抓包!
首先想到的是,用fiddler抓Postman的數(shù)據(jù)包,然后C#程序構(gòu)造同樣的數(shù)據(jù)包即可。
觀(guān)察數(shù)據(jù)包Headers選項(xiàng)卡,如圖:
發(fā)現(xiàn)Content-Type: multipart/form-data;后面跟了一個(gè)boundary=----------------------------183584948778966847113836
并且TextView選項(xiàng)卡如下:
WebForms選項(xiàng)卡如下:
所以,可以按照Headers和TextView選項(xiàng)卡內(nèi)容構(gòu)造post請(qǐng)求,就可以解決我們的問(wèn)題了!
3.解決步驟
將ContentType加上boundary=boundary-------------------------xxxxxxxxxxxxxx
并且構(gòu)造參數(shù),如下:
string url = "http://112.17.158.12:8180/intf/services/query"; string boundary = "--------------------------" + DateTime.Now.Ticks.ToString("x"); string boundary2 = "--" + boundary; HttpWebRequest request = WebRequest.Create(new Uri(url)) as HttpWebRequest; request.Method = "POST"; request.Host = "112.17.158.12:8180"; request.ContentType = "multipart/form-data; boundary=" + boundary; request.UserAgent = "PostmanRuntime/7.17.1"; request.Accept = "*/*"; request.KeepAlive = true; StringBuilder sb = new StringBuilder(); sb.Append(boundary2 + "\r\n"); sb.Append(@"Content-Disposition: form-data; name=""jkuser""" + "\r\n\r\n"); sb.Append("33088102" + "\r\n"); sb.Append(boundary2 + "\r\n"); sb.Append(@"Content-Disposition: form-data; name=""jkpasswd""" + "\r\n\r\n"); sb.Append("33088102" + "\r\n"); sb.Append(boundary2 + "\r\n"); sb.Append(@"Content-Disposition: form-data; name=""jsondata""" + "\r\n\r\n"); sb.Append(@"{""jkid"":""R10"",""requestTime"":""20190919110603"",""body"":[{""inspstationcode"":""33088102""}]}" + "\r\n"); sb.Append(boundary2 + "--" + "\r\n"); string postData = sb.ToString(); byte[] postdatabyte = Encoding.GetEncoding("utf-8").GetBytes(postData); request.ContentLength = postdatabyte.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(postdatabyte, 0, postdatabyte.Length); } HttpWebResponse response = request.GetResponse() as HttpWebResponse; using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8"))) { string temp = reader.ReadToEnd(); }
值得注意的是,“boundary-------------------------xxxxxxxxxxxxxx”
這么長(zhǎng)一串東西,只是作為分隔符出現(xiàn)的,不必太在意它是什么東西,我將它理解為分割文本參數(shù)的這么一個(gè)東西,并且通過(guò)仔細(xì)觀(guān)察發(fā)現(xiàn)可以發(fā)現(xiàn)header中contenttype的橫線(xiàn)數(shù)量比參數(shù)中橫線(xiàn)數(shù)量少兩個(gè)且必須少兩個(gè)?
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#中動(dòng)態(tài)顯示當(dāng)前系統(tǒng)時(shí)間的實(shí)例方法
想在網(wǎng)頁(yè)中動(dòng)態(tài)地顯示當(dāng)前系統(tǒng)的時(shí)間,找了好多,不過(guò)都是一些停在那里不動(dòng)的。。。不過(guò)皇天不負(fù)有心人,終于讓我找到了2013-05-05C#使用ZBar實(shí)現(xiàn)識(shí)別條形碼
目前主流的識(shí)別庫(kù)主要有ZXing.NET和ZBar,本文主要介紹的是如何使用ZBar庫(kù)實(shí)現(xiàn)識(shí)別條形碼功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-07-07C#操作NPOI實(shí)現(xiàn)Excel數(shù)據(jù)導(dǎo)入導(dǎo)出
這篇文章主要為大家詳細(xì)介紹了C#如何操作NPOI實(shí)現(xiàn)Excel數(shù)據(jù)導(dǎo)入導(dǎo)出功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-02-02C#中定時(shí)任務(wù)被阻塞問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于C#中定時(shí)任務(wù)被阻塞問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用c#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-11-11Winform+.Net6實(shí)現(xiàn)圖片拖拽上傳功能
這篇文章主要為大家詳細(xì)介紹了如何使用WinformPictureBox控件+.Net6 WebApi實(shí)現(xiàn)圖片拖拽上傳功能,文中的示例代碼講解詳細(xì),感興趣的可以學(xué)習(xí)一下2023-09-09