天天看點

C#實作http協定支援上傳下載下傳檔案的GET、POST請求

 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; }         }     } }