C#中后臺post請求常用的兩種方式總結(jié)
最近對接接口的時候,需要根據(jù)對方的請求數(shù)據(jù)類型來進行傳值,常用的就是application/x-www-form-urlencoded,ajax提交數(shù)據(jù)時也是使用的這種方式,但是沒辦法傳遞文件之類的信息,另一種就是mutipart/form-data,可以同時傳遞參數(shù)與文件或二進制流,這里主要使用的就是這兩種方式
1.application/x-www-form-urlencoded
首先創(chuàng)建一個HttpWebRequest,并且聲明請求方法和請求頭
程序使用HTTP協(xié)議和服務(wù)器交互主要是進行數(shù)據(jù)的提交,通常數(shù)據(jù)的提交是通過 GET 和 POST 兩種方式來完成,
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded;charset:utf-8";
然后,我們需要進行拼接參數(shù),這種請求方式,提交的數(shù)據(jù)按照 key1=val1&key2=val2 的方式進行編碼,key 和 val 都進行了 URL 轉(zhuǎn)碼。
大部分服務(wù)端語言都對這種方式有很好的支持,這里使用foreach進行循環(huán)拼接
StringBuilder paraStrBuilder = new StringBuilder();
foreach (string key in postParameters.Keys)
{
paraStrBuilder.AppendFormat("{0}={1}&", key, postParameters[key]);
}
string para = paraStrBuilder.ToString();
if (para.EndsWith("&"))
para = para.Remove(para.Length - 1, 1);接著,將參數(shù)轉(zhuǎn)為ASCII碼,并且將參數(shù)寫入請求中
byte[] bt = Encoding.UTF8.GetBytes(para);
string responseData = String.Empty;
request.ContentLength = bt.Length;
//GetRequestStream 輸入流數(shù)據(jù)
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(bt, 0, bt.Length);
reqStream.Close();
}后面就是發(fā)送請求,獲取響應(yīng)內(nèi)容
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream stream = response.GetResponseStream();
using (StreamReader streamReader = new StreamReader(stream, Encoding.UTF8))
{
retString = streamReader.ReadToEnd().ToString();
}
}這樣,一個完整的post請求就完成了,還是比較簡單的
2.mutipart/form-data
這種方式就比較麻煩了,常用于表單提交文件數(shù)據(jù)并且包含參數(shù)的形式,我們可以先通過postman請求,看一下請求正文是什么內(nèi)容

這個是一個附件上傳的接口,包含了附件信息和一些參數(shù)信息,首先聲明了請求類型是mutipart/form-data,后面跟了一個boundary,并且內(nèi)容是隨機的,緊接著又以一段隨機字符串開始,聲明了第一個參數(shù)名name=“file”,然后換了兩行,跟了文件信息,又是以同樣的一段的字符串進行分割,拼接下一段參數(shù)信息,這個地方多試幾遍,并且看看他的結(jié)構(gòu)就能很好的寫代碼了
我們這里演示兩種方式,方便大家理解,一種是參數(shù)里不含任何文件信息,只有keyvalue,另一種是包含了文件信息且還有額外參數(shù)
首先是第一種,沒有文件信息
還是先創(chuàng)建一個http并聲明請求頭
var webRequest = (HttpWebRequest)WebRequest.Create(strUrl);
var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
// 邊界符
var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
// 最后的結(jié)束符
var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
memStream.Write(beginBoundary, 0, beginBoundary.Length);
// 設(shè)置屬性
webRequest.Method = "POST";
webRequest.Timeout = 10000;
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;第二行創(chuàng)建一個boundary作為分割字符,然后在聲明一個起始位置與結(jié)束位置,詳見postm請求圖中第5行和第30行,就是起始標(biāo)識與結(jié)束標(biāo)識,并創(chuàng)建一個MemoryStream,不斷的寫入
然后進行參數(shù)拼接,這里要注意上圖里,每個參數(shù)的格式
foreach (string key in postParameters.Keys)
{
var stringKeyHeader = "Content-Disposition: form-data; name=\"{0}\"" + "\r\n\r\n{1}\r\n";
var header = string.Format(stringKeyHeader, key, postParameters[key]);
var headerbytes = Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
}每一個Content-Disposition: form-data; name=""后,進行了兩次換行,才拼接了值,然后又進行了一次換行沒有文件信息就不拼接間隔值,繼續(xù)拼接下一個值,在所有的值拼接完成后,加上結(jié)束標(biāo)識
memStream.Write(endBoundary, 0, endBoundary.Length);
然后將拼接完成的流,重新寫入請求流中
webRequest.ContentLength = memStream.Length;
var requestStream = webRequest.GetRequestStream();
memStream.Position = 0;
var tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();后面就是發(fā)送請求,拿回響應(yīng)內(nèi)容
using (HttpWebResponse res = (HttpWebResponse)webRequest.GetResponse())
{
using (Stream resStream = res.GetResponseStream())
{
byte[] buffer = new byte[1024];
int read;
while ((read = resStream.Read(buffer, 0, buffer.Length)) > 0)
{
responseContent += Encoding.UTF8.GetString(buffer, 0, read);
}
}
res.Close();
}
return responseContent;到此,不包含文件信息的請求就完成了
第二種,包含了文件信息,且也包含參數(shù),本質(zhì)上只是多了一步單獨的拼接步驟,所以這步可以放在所有的參數(shù)拼接完成后,緊接著繼續(xù)拼接文件信息參數(shù),所以這一步的代碼,應(yīng)該放在foreach之后且在foreach里需要拼接間隔值,這里就只放這一塊的代碼了,注意,如果在foreach之后還要繼續(xù)拼接參數(shù),就不要加結(jié)束標(biāo)識
const string filePartHeader =
"Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
var header1 = string.Format(filePartHeader, postParameters["realName"]);
var headerbytes1 = Encoding.UTF8.GetBytes(header1);
memStream.Write(headerbytes1, 0, headerbytes1.Length);
memStream.Write(FileByte, 0, FileByte.Length);
string end = "\r\n";
headerbytes1 = Encoding.UTF8.GetBytes(end);
memStream.Write(headerbytes1, 0, headerbytes1.Length);
memStream.Write(endBoundary, 0, endBoundary.Length);先按照格式編寫參數(shù)名Content-Disposition: form-data; name=""; filename="" Content-Type: ,然后連續(xù)換兩行,寫入文件流,在換行寫入結(jié)束標(biāo)識,后面步驟就一樣,只要看懂了開始的那張圖,剩下的都是按照格式去拼接寫入就好
到此帶文件信息的傳參也完成了,接觸的越多,能學(xué)習(xí)的就越多,會的越多,不會的就越多,還有其他的請求方式我這里就不在詳細介紹了!
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C# Winform 實現(xiàn)控件自適應(yīng)父容器大小的示例代碼
這篇文章主要介紹了C# Winform 實現(xiàn)控件自適應(yīng)父容器大小的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
詳解C#如何在不同工作簿之間復(fù)制選定單元格區(qū)域
處理Excel文檔時,我們經(jīng)常需要將數(shù)據(jù)整合到一個工作表以便于我們進行管理或數(shù)據(jù)對比。本文將演示如何通過編程方式將選定的單元格區(qū)域從一個工作簿復(fù)制到另一個工作簿2023-02-02
C#實現(xiàn)日期格式轉(zhuǎn)換的公共方法類實例
這篇文章主要介紹了C#實現(xiàn)日期格式轉(zhuǎn)換的公共方法類,結(jié)合完整實例形式分析了C#針對各種常見日期格式的轉(zhuǎn)換方法,涉及C#字符串、日期、時間相關(guān)操作技巧,需要的朋友可以參考下2017-01-01
C#使用偽隨機數(shù)實現(xiàn)加密用戶密碼的方法
這篇文章主要介紹了C#使用偽隨機數(shù)實現(xiàn)加密用戶密碼的方法,對于開發(fā)C#會員系統(tǒng)或者程序安全問題都有一定的參考借鑒價值,需要的朋友可以參考下2014-07-07
c#將字節(jié)數(shù)組轉(zhuǎn)成易讀的字符串的實現(xiàn)
這篇文章主要介紹了c#將字節(jié)數(shù)組轉(zhuǎn)成易讀的字符串的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01

