C#實作http協定 支援上傳下載下傳檔案的 GET、POST請求
using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; using System.Collections; using System.IO; using System.Text.RegularExpressions; using RE = System.Text.RegularExpressions.Regex; using System.Security.Cryptography.X509Certificates; namespace HttpProc { ///<summary> /// 上傳事件委托 ///</summary> ///<param name="sender"></param> ///<param name="e"></param> public delegate void WebClientUploadEvent(object sender, HttpProc.UploadEventArgs e); ///<summary> /// 下載下傳事件委托 ///</summary> ///<param name="sender"></param> ///<param name="e"></param> public delegate void WebClientDownloadEvent(object sender, HttpProc.DownloadEventArgs e); ///<summary> /// 上傳事件參數 ///</summary> public struct UploadEventArgs { ///<summary> /// 上傳資料總大小 ///</summary> public long totalBytes; ///<summary> /// 已發資料大小 ///</summary> public long bytesSent; ///<summary> /// 發送進度(0-1) ///</summary> public double sendProgress; ///<summary> /// 發送速度Bytes/s ///</summary> public double sendSpeed; } ///<summary> /// 下載下傳事件參數 ///</summary> public struct DownloadEventArgs { ///<summary> /// 下載下傳資料總大小 ///</summary> public long totalBytes; ///<summary> /// 已接收資料大小 ///</summary> public long bytesReceived; ///<summary> /// 接收資料進度(0-1) ///</summary> public double ReceiveProgress; ///<summary> /// 目前緩沖區資料 ///</summary> public byte[] receivedBuffer; ///<summary> /// 接收速度Bytes/s ///</summary> public double receiveSpeed; } ///<summary> /// 實作向WEB伺服器發送和接收資料 ///</summary> public class WebClient { private WebHeaderCollection requestHeaders, responseHeaders; private TcpClient clientSocket; private MemoryStream postStream; private Encoding encoding = Encoding.Default; private const string BOUNDARY = "--HEDAODE--"; private const int SEND_BUFFER_SIZE = 10245; private const int RECEIVE_BUFFER_SIZE = 10245; private string cookie = ""; private string respHtml = ""; private string strRequestHeaders = ""; private string strResponseHeaders = ""; private int statusCode = 0; private bool isCanceled = false; public event WebClientUploadEvent UploadProgressChanged; public event WebClientDownloadEvent DownloadProgressChanged; ///<summary> /// 初始化WebClient類 ///</summary> public WebClient() { responseHeaders = new WebHeaderCollection(); requestHeaders = new WebHeaderCollection(); } ///<summary> /// 讀取指定URL的文本 ///</summary> ///<param name="URL"> 請求的位址 </param> ///<returns> 伺服器響應文本 </returns> public string OpenRead(string URL) { requestHeaders.Add("Connection", "close"); SendRequestData(URL, "GET"); return GetHtml(); } // 解決證書過期無法通路的問題 class CertPolicy : ICertificatePolicy { public bool CheckValidationResult(ServicePoint srvpt, X509Certificate cert, WebRequest req, int certprb) { return true; } } ///<summary> /// 采用https協定通路網絡 ///</summary> ///<param name="URL">url 位址 </param> ///<param name="strPostdata"> 發送的資料 </param> ///<returns></returns> public string OpenReadWithHttps(string URL,string strPostdata) { ServicePointManager.CertificatePolicy = new CertPolicy(); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL); request.CookieContainer = new CookieContainer(); request.Method = "POST"; request.Accept = "**"); requestHeaders.Add("Accept-Language", "zh-cn"); requestHeaders.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"); string headers = request + "/r/n"; foreach (string key in requestHeaders) { headers += key + ":" + requestHeaders[key] + "/r/n"; } // 有Cookie就帶上Cookie if (cookie != "") { headers += "Cookie:" + cookie + "/r/n"; } // 空行,請求頭結束 headers += "/r/n"; strRequestHeaders = headers; requestHeaders.Clear(); return encoding.GetBytes(headers); } ///<summary> /// 擷取伺服器響應文本 ///</summary> ///<returns> 伺服器響應文本 </returns> private string GetHtml() { MemoryStream ms = new MemoryStream(); SaveNetworkStream(ms);// 将網絡流儲存到記憶體流 StreamReader sr = new StreamReader(ms, encoding); respHtml = sr.ReadToEnd(); sr.Close(); ms.Close(); return respHtml; } ///<summary> /// 将網絡流儲存到指定流 ///</summary> ///<param name="toStream"> 儲存位置 </param> ///<param name="needProgress"> 是否顯示進度 </param> private void SaveNetworkStream(Stream toStream, bool showProgress) { // 擷取要儲存的網絡流 NetworkStream NetStream = clientSocket.GetStream(); byte[] buffer = new byte[RECEIVE_BUFFER_SIZE]; int count = 0, startIndex = 0; MemoryStream ms = new MemoryStream(); for (int i = 0; i < 3; i++) { count = NetStream.Read(buffer, 0, 500); ms.Write(buffer, 0, count); } if (ms.Length == 0) { NetStream.Close(); throw new Exception(" 遠端伺服器沒有響應" ); } buffer = ms.GetBuffer(); count = (int)ms.Length; GetResponseHeader(buffer, out startIndex);// 分析響應,擷取響應頭和響應實體 count -= startIndex; toStream.Write(buffer, startIndex, count); DownloadEventArgs e = new DownloadEventArgs(); if (responseHeaders["Content-Length"] != null) { e.totalBytes = long.Parse(responseHeaders["Content-Length"]); } else { e.totalBytes = -1; } // 啟動計時器 System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); timer.Start(); do { // 如果取消就推出 if (isCanceled) { break; } // 顯示下載下傳進度 if (showProgress) { e.bytesReceived += count; e.ReceiveProgress = (double)e.bytesReceived / (double)e.totalBytes; byte[] tempBuffer = new byte[count]; Array.Copy(buffer, startIndex, tempBuffer, 0, count); e.receivedBuffer = tempBuffer; double t = (timer.ElapsedMilliseconds + 0.1)/1000; e.receiveSpeed = (double)e.bytesReceived / t; startIndex = 0; if (DownloadProgressChanged != null) { DownloadProgressChanged(this, e); } } // 讀取網路資料到緩沖區 count = NetStream.Read(buffer, 0, buffer.Length); // 将緩存區資料儲存到指定流 toStream.Write(buffer, 0, count); } while (count > 0); timer.Stop();// 關閉計時器 if (responseHeaders["Content-Length"] != null) { toStream.SetLength(long.Parse(responseHeaders["Content-Length"])); } //else //{ // toStream.SetLength(toStream.Length); // responseHeaders.Add("Content-Length", toStream.Length.ToString());// 添加響應标頭 //} toStream.Position = 0; // 關閉網絡流和網絡連接配接 NetStream.Close(); clientSocket.Close(); } ///<summary> /// 将網絡流儲存到指定流 ///</summary> ///<param name="toStream"> 儲存位置 </param> private void SaveNetworkStream(Stream toStream) { SaveNetworkStream(toStream, false); } ///<summary> /// 分析響應流,去掉響應頭 ///</summary> ///<param name="buffer"></param> private void GetResponseHeader(byte[] buffer, out int startIndex) { responseHeaders.Clear(); string html = encoding.GetString(buffer); StringReader sr = new StringReader(html); int start = html.IndexOf("/r/n/r/n") + 4;// 找到空行位置 strResponseHeaders = html.Substring(0, start);// 擷取響應頭文本 // 擷取響應狀态碼 // if (sr.Peek() > -1) { // 讀第一行字元串 string line = sr.ReadLine(); // 分析此行字元串,擷取伺服器響應狀态碼 Match M = RE.Match(line, @"/d/d/d"); if (M.Success) { statusCode = int.Parse(M.Value); } } // 擷取響應頭 // while (sr.Peek() > -1) { // 讀一行字元串 string line = sr.ReadLine(); // 若非空行 if (line != "") { // 分析此行字元串,擷取響應标頭 Match M = RE.Match(line, "([^:]+):(.+)"); if (M.Success) { try { // 添加響應标頭到集合 responseHeaders.Add(M.Groups[1].Value.Trim(), M.Groups[2].Value.Trim()); } catch { } // 擷取Cookie if (M.Groups[1].Value == "Set-Cookie") { M = RE.Match(M.Groups[2].Value, "[^=]+=[^;]+"); cookie += M.Value.Trim() + ";"; } } } // 若是空行,代表響應頭結束響應實體開始。(響應頭和響應實體間用一空行隔開) else { // 如果響應頭中沒有實體大小标頭,嘗試讀響應實體第一行擷取實體大小 if (responseHeaders["Content-Length"] == null && sr.Peek() > -1) { // 讀響應實體第一行 line = sr.ReadLine(); // 分析此行看是否包含實體大小 Match M = RE.Match(line, "~[0-9a-fA-F]{1,15}"); if (M.Success) { // 将16進制的實體大小字元串轉換為10進制 int length = int.Parse(M.Value, System.Globalization.NumberStyles.AllowHexSpecifier); responseHeaders.Add("Content-Length", length.ToString());// 添加響應标頭 strResponseHeaders += M.Value + "/r/n"; } } break;// 跳出循環 }//End If }//End While sr.Close(); // 實體開始索引 startIndex = encoding.GetBytes(strResponseHeaders).Length; } ///<summary> /// 取消上傳或下載下傳,要繼續開始請調用Start方法 ///</summary> public void Cancel() { isCanceled = true; } ///<summary> /// 啟動上傳或下載下傳,要取消請調用Cancel方法 ///</summary> public void Start() { isCanceled = false; } //************************************************************* // 以下為屬性 //************************************************************* ///<summary> /// 擷取或設定請求頭 ///</summary> public WebHeaderCollection RequestHeaders { set { requestHeaders = value; } get { return requestHeaders; } } ///<summary> /// 擷取響應頭集合 ///</summary> public WebHeaderCollection ResponseHeaders { get { return responseHeaders; } } ///<summary> /// 擷取請求頭文本 ///</summary> public string StrRequestHeaders { get { return strRequestHeaders; } } ///<summary> /// 擷取響應頭文本 ///</summary> public string StrResponseHeaders { get { return strResponseHeaders; } } ///<summary> /// 擷取或設定Cookie ///</summary> public string Cookie { set { cookie = value; } get { return cookie; } } ///<summary> /// 擷取或設定編碼方式(預設為系統預設編碼方式) ///</summary> public Encoding Encoding { set { encoding = value; } get { return encoding; } } ///<summary> /// 擷取伺服器響應文本 ///</summary> public string RespHtml { get { return respHtml; } } ///<summary> /// 擷取伺服器響應狀态碼 ///</summary> public int StatusCode { get { return statusCode; } } } }