C#中后臺(tái)post請(qǐng)求常用的兩種方式總結(jié)
最近對(duì)接接口的時(shí)候,需要根據(jù)對(duì)方的請(qǐng)求數(shù)據(jù)類型來進(jìn)行傳值,常用的就是application/x-www-form-urlencoded,ajax提交數(shù)據(jù)時(shí)也是使用的這種方式,但是沒辦法傳遞文件之類的信息,另一種就是mutipart/form-data,可以同時(shí)傳遞參數(shù)與文件或二進(jìn)制流,這里主要使用的就是這兩種方式
1.application/x-www-form-urlencoded
首先創(chuàng)建一個(gè)HttpWebRequest,并且聲明請(qǐng)求方法和請(qǐng)求頭
程序使用HTTP協(xié)議和服務(wù)器交互主要是進(jìn)行數(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";
然后,我們需要進(jìn)行拼接參數(shù),這種請(qǐng)求方式,提交的數(shù)據(jù)按照 key1=val1&key2=val2 的方式進(jìn)行編碼,key 和 val 都進(jìn)行了 URL 轉(zhuǎn)碼。
大部分服務(wù)端語言都對(duì)這種方式有很好的支持,這里使用foreach進(jìn)行循環(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ù)寫入請(qǐng)求中
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ā)送請(qǐng)求,獲取響應(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();
}
}這樣,一個(gè)完整的post請(qǐng)求就完成了,還是比較簡單的
2.mutipart/form-data
這種方式就比較麻煩了,常用于表單提交文件數(shù)據(jù)并且包含參數(shù)的形式,我們可以先通過postman請(qǐng)求,看一下請(qǐng)求正文是什么內(nèi)容

這個(gè)是一個(gè)附件上傳的接口,包含了附件信息和一些參數(shù)信息,首先聲明了請(qǐng)求類型是mutipart/form-data,后面跟了一個(gè)boundary,并且內(nèi)容是隨機(jī)的,緊接著又以一段隨機(jī)字符串開始,聲明了第一個(gè)參數(shù)名name=“file”,然后換了兩行,跟了文件信息,又是以同樣的一段的字符串進(jìn)行分割,拼接下一段參數(shù)信息,這個(gè)地方多試幾遍,并且看看他的結(jié)構(gòu)就能很好的寫代碼了
我們這里演示兩種方式,方便大家理解,一種是參數(shù)里不含任何文件信息,只有keyvalue,另一種是包含了文件信息且還有額外參數(shù)
首先是第一種,沒有文件信息
還是先創(chuàng)建一個(gè)http并聲明請(qǐng)求頭
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)建一個(gè)boundary作為分割字符,然后在聲明一個(gè)起始位置與結(jié)束位置,詳見postm請(qǐng)求圖中第5行和第30行,就是起始標(biāo)識(shí)與結(jié)束標(biāo)識(shí),并創(chuàng)建一個(gè)MemoryStream,不斷的寫入
然后進(jìn)行參數(shù)拼接,這里要注意上圖里,每個(gè)參數(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);
}每一個(gè)Content-Disposition: form-data; name=""后,進(jìn)行了兩次換行,才拼接了值,然后又進(jìn)行了一次換行沒有文件信息就不拼接間隔值,繼續(xù)拼接下一個(gè)值,在所有的值拼接完成后,加上結(jié)束標(biāo)識(shí)
memStream.Write(endBoundary, 0, endBoundary.Length);
然后將拼接完成的流,重新寫入請(qǐng)求流中
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ā)送請(qǐng)求,拿回響應(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;到此,不包含文件信息的請(qǐng)求就完成了
第二種,包含了文件信息,且也包含參數(shù),本質(zhì)上只是多了一步單獨(dú)的拼接步驟,所以這步可以放在所有的參數(shù)拼接完成后,緊接著繼續(xù)拼接文件信息參數(shù),所以這一步的代碼,應(yīng)該放在foreach之后且在foreach里需要拼接間隔值,這里就只放這一塊的代碼了,注意,如果在foreach之后還要繼續(xù)拼接參數(shù),就不要加結(jié)束標(biāo)識(shí)
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)識(shí),后面步驟就一樣,只要看懂了開始的那張圖,剩下的都是按照格式去拼接寫入就好
到此帶文件信息的傳參也完成了,接觸的越多,能學(xué)習(xí)的就越多,會(huì)的越多,不會(huì)的就越多,還有其他的請(qǐng)求方式我這里就不在詳細(xì)介紹了!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
字符串替換Replace僅替換第一個(gè)字符串匹配項(xiàng)
C#里面的String.Replace(string,string)方法替換的時(shí)候是替換所有的匹配項(xiàng),我們需要只替換第一個(gè)匹配項(xiàng),寫一個(gè)方法來實(shí)現(xiàn)這個(gè)功能2013-12-12
C#使用委托(delegate)實(shí)現(xiàn)在兩個(gè)form之間傳遞數(shù)據(jù)的方法
這篇文章主要介紹了C#使用委托(delegate)實(shí)現(xiàn)在兩個(gè)form之間傳遞數(shù)據(jù)的方法,涉及C#委托的使用技巧,需要的朋友可以參考下2015-04-04
基于Silverlight打印的使用詳解,是否為微軟的Bug問題
本篇文章對(duì)Silverlight打印的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C# 中 Array和 ArrayList詳解及區(qū)別
這篇文章主要介紹了C# 中 Array和 ArrayList詳解及區(qū)別的相關(guān)資料,需要的朋友可以參考下2017-01-01

