新年开篇,忙归忙,还是要写点什么,不然越来越懒,分享我写的HttpTooler
public delegate void RequestCompleted(object sender, string html); public enum RequestType { WebRequest, HttpClient, WebClient } public class HttpTooler { private static byte[] postBuffer; //private HttpWebRequest request; private const string contentType = "application/x-www-form-urlencoded;charset=utf-8"; private const string multipartType = "multipart/form-data; boundary="; private const string formBoundary = "----WebKitFormBoundary"; private const string accept = "text/html, application/xhtml+xml, */*"; private const string userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36"; private const string cacheCtr = "Cache-Control"; private const string noCache = "no-cache"; private bool changeFlag; private string oldDomain; private string newDomain; public CookieContainer container; public RequestCompleted RequestCompleted { private get; set; } public HttpTooler() { container = new CookieContainer(); } public HttpTooler(CookieContainer container) { this.container = container; } public void FixCookieDomain(string oldstr, string newstr) { changeFlag = true; oldDomain = oldstr; newDomain = newstr; } private void GetRequestHtml(string url) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.KeepAlive = true; request.Timeout = 30000; request.ContentType = contentType; request.Accept = accept; request.UserAgent = userAgent; request.Headers.Add(cacheCtr, noCache); request.AllowAutoRedirect = false; request.CookieContainer = container; request.KeepAlive = true; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); string html = string.Empty; using (Stream sw = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(sw)) { html = reader.ReadToEnd(); } if (changeFlag) FixCookieDomain(response); } if (response != null) response.Close(); DoCompleted(html); } public void GetHtml(RequestType type, string url) { if (type == RequestType.WebRequest) { GetRequestHtml(url); } else if (type == RequestType.WebClient) { GetWebClientHtml(url); } else { GetHttpClientHtml(url); } } private void GetWebClientHtml(string url) { WebClient wc = new WebClient(); wc.Credentials = CredentialCache.DefaultCredentials; byte[] data = wc.DownloadData(url); string html = Encoding.UTF8.GetString(data); DoCompleted(html); } private void GetHttpClientHtml(string url) { HttpClient hc = new HttpClient(container); hc.Credentials = CredentialCache.DefaultCredentials; byte[] data = hc.DownloadData(url); string html = Encoding.UTF8.GetString(data); DoCompleted(html); } public void PostData(string url, string param, string referer) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; if (string.IsNullOrEmpty(referer)) request.Referer = referer; request.KeepAlive = true; request.Timeout = 30000; request.ContentType = contentType; request.Accept = accept; request.UserAgent = userAgent; request.Headers.Add(cacheCtr, noCache); request.AllowAutoRedirect = false; request.CookieContainer = container; request.KeepAlive = true; byte[] buff = Encoding.UTF8.GetBytes(param); Stream reqStream = request.GetRequestStream(); reqStream.Write(buff, 0, buff.Length); reqStream.Close(); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); string html = string.Empty; using (Stream sw = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(sw)) { html = reader.ReadToEnd(); } string strcook = response.Headers["Set-Cookie"]; if (changeFlag) FixCookieDomain(response); } if (response != null) response.Close(); DoCompleted(html); } public void PostDataAsync(string url, string param) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.KeepAlive = true; request.Timeout = 30000; request.ContentType = contentType; request.CookieContainer = container; postBuffer = Encoding.UTF8.GetBytes(param); request.BeginGetRequestStream(new AsyncCallback(RequestStreamAsync), request); } private void DoCompleted(string rlt) { if (RequestCompleted != null) { RequestCompleted(this, rlt); } } private void RequestStreamAsync(IAsyncResult result) { HttpWebRequest request = (HttpWebRequest)result.AsyncState; Stream reqStream = request.EndGetRequestStream(result); reqStream.Write(postBuffer, 0, postBuffer.Length); reqStream.Close(); request.BeginGetResponse(new AsyncCallback(ResponseAsync), request); } private void ResponseAsync(IAsyncResult result) { HttpWebRequest req = (HttpWebRequest)result.AsyncState; HttpWebResponse response = (HttpWebResponse)req.EndGetResponse(result); string html = string.Empty; using (Stream sw = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(sw)) { html = reader.ReadToEnd(); } } if (response != null) response.Close(); DoCompleted(html); } public void MultiPostData(string url, string referer, Dictionary<string, string> PostData) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.KeepAlive = true; request.Timeout = 30000; string boundary = formBoundary + DateTime.Now.Ticks.ToString("x"); request.ContentType = string.Format("{0}{1}", multipartType, boundary); request.Accept = accept; request.UserAgent = userAgent; request.Headers.Add(cacheCtr, noCache); request.AllowAutoRedirect = false; request.CookieContainer = container; request.ServicePoint.Expect100Continue = false; if (referer != string.Empty) request.Referer = referer; byte[] buff = BuildMultiPostData(boundary, PostData); BinaryWriter bw = new BinaryWriter(request.GetRequestStream()); bw.Write(buff); bw.Close(); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); string html = string.Empty; using (Stream sw = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(sw)) { html = reader.ReadToEnd(); } //第一次提交修改cookie if (changeFlag) { FixCookieDomain(response); } } if (response != null) response.Close(); DoCompleted(html); } private byte[] BuildMultiPostData(string boundary, Dictionary<string, string> postData) { StringBuilder sb = new StringBuilder(); // append access token. //sb.AppendLine("--" + boundary); //sb.Append(Environment.NewLine); // append form part. if (postData != null && postData.Count > 0) { foreach (KeyValuePair<string, string> HttpPostDataItem in postData) { sb.AppendLine("--" + boundary); sb.AppendLine(string.Format("Content-Disposition: form-data;name="{0}"", HttpPostDataItem.Key)); sb.Append(Environment.NewLine); sb.AppendLine(HttpPostDataItem.Value); } } MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); bw.Write(Encoding.UTF8.GetBytes(sb.ToString())); bw.Write(Encoding.UTF8.GetBytes(Environment.NewLine)); bw.Write(Encoding.UTF8.GetBytes("--" + boundary + "--")); bw.Write(Encoding.UTF8.GetBytes(Environment.NewLine)); ms.Flush(); ms.Position = 0; byte[] result = ms.ToArray(); bw.Close(); return result; } private void FixCookieDomain(HttpWebResponse response) { string strCookie = response.Headers["Set-Cookie"]; CookieCollection collect = GetCookiesFromReponseHead(strCookie, oldDomain); foreach (Cookie cook in collect) { Cookie ncook = new Cookie(); ncook.Domain = oldDomain; ncook.Name = cook.Name; ncook.Value = cook.Value; Cookie pcook = FindCookie(newDomain, cook.Name); if (pcook == null) { container.Add(ncook); } else { pcook = ncook; } } changeFlag = false; } private CookieCollection GetCookiesFromReponseHead(string setCookieHeadStr, string defaultDomain) { CookieCollection cookies = new CookieCollection(); if (!string.IsNullOrEmpty(setCookieHeadStr)) { setCookieHeadStr = setCookieHeadStr.Replace("HttpOnly,", string.Empty).Replace("httponly", string.Empty); foreach (string str in setCookieHeadStr.Split(new string[] { "Path=/,", "path=/,", "path=/;", "Path=/;", "PATH=/;" }, StringSplitOptions.None)) { string cookieString = str.Trim(); if (cookieString.IndexOf(',') == 0) { cookieString = cookieString.Substring(1); } try { Cookie cookieFromString = GetCookieFromString(cookieString, defaultDomain); if (cookieFromString != null) { cookies.Add(cookieFromString); } } catch (Exception exception) { //LogManager.Error("GetCookiesFromReponseHead", exception); } } } return cookies; } private static Cookie GetCookieFromString(string cookieString, string defaultDomain) { Cookie cookie = new Cookie(); string[] strArray = cookieString.Split(new char[] { ';', ',' }); int index = strArray[0].IndexOf("="); if (index == -1) { return null; } if (!strArray[0].ToLower().StartsWith("domain=") && !strArray[0].ToLower().StartsWith("expires=")) { cookie.Name = strArray[0].Substring(0, index); cookie.Value = strArray[0].Substring(index + 1); } else { bool flag = false; if (strArray[0].ToLower().StartsWith("domain=") && strArray[0].Contains(",")) { strArray[0] = strArray[0].Substring(strArray[0].IndexOf(',') + 1); index = strArray[0].IndexOf("="); if (index > -1) { cookie.Name = strArray[0].Substring(0, index); cookie.Value = strArray[0].Substring(index + 1); flag = true; } } if (!flag) { for (int j = 1; j < strArray.Length; j++) { index = strArray[j].IndexOf("="); if (index > 0) { string str = strArray[j].Substring(0, index); if ((!str.ToLower().StartsWith("domain=") && !str.ToLower().StartsWith("expires=")) && !str.ToLower().StartsWith("version=")) { string str2 = strArray[j].Substring(index + 1); cookie.Name = str.Replace(",", "").Trim(); cookie.Value = str2; flag = true; break; } } } } if (!flag) { return null; } } Hashtable hashtable = new Hashtable(); for (int i = 0; i < strArray.Length; i++) { if (!string.IsNullOrEmpty(strArray[i])) { string str3 = strArray[i].Trim(); int length = str3.IndexOf("="); if (length > 0) { string key = str3.Substring(0, length); if (!hashtable.ContainsKey(key)) { string str5 = str3.Substring(length + 1); hashtable.Add(key, str5); } } } } foreach (object obj2 in hashtable.Keys) { if (obj2.ToString().ToLower() == "path") { cookie.Path = hashtable[obj2].ToString(); } else if (obj2.ToString().ToLower() == "expires") { DateTime time; if (DateTime.TryParse(hashtable[obj2].ToString(), out time)) { cookie.Expires = time; } } else if (obj2.ToString().ToLower() == "domain") { if (hashtable[obj2].ToString().ToLower() == "koubei.com") { cookie.Domain = "." + hashtable[obj2].ToString(); } else if (hashtable[obj2].ToString().ToLower() == "58.com") { cookie.Domain = "." + hashtable[obj2].ToString(); } else { cookie.Domain = hashtable[obj2].ToString(); } } else if (obj2.ToString().ToLower() == "version") { cookie.Version = int.Parse(hashtable[obj2].ToString()); } else if (!(obj2.ToString().ToLower() == "max-age")) { cookie.Expires = new DateTime(0x802, 1, 1); cookie.Expired = false; } } if (cookie.Name == "") { return null; } if (cookie.Domain == "") { cookie.Domain = defaultDomain; } return cookie; } private Cookie FindCookie(string Url, string name) { if (Url.Substring(0, 5).ToLower() != "http:") { Url += "http://" + Url; } CookieCollection cookies = container.GetCookies(new Uri(Url)); if (cookies != null) { foreach (Cookie cookie in cookies) { if (cookie.Name == name) { return cookie; } } } return null; } } class HttpClient : WebClient { // Cookie 容器 private CookieContainer cookieContainer; /**/ /// <summary> /// 创建一个新的 WebClient 实例。 /// </summary> public HttpClient() { this.cookieContainer = new CookieContainer(); } /**/ /// <summary> /// 创建一个新的 WebClient 实例。 /// </summary> /// <param name="cookie">Cookie 容器</param> public HttpClient(CookieContainer cookies) { this.cookieContainer = cookies; } /**/ /// <summary> /// Cookie 容器 /// </summary> public CookieContainer Cookies { get { return this.cookieContainer; } set { this.cookieContainer = value; } } /**/ /// <summary> /// 返回带有 Cookie 的 HttpWebRequest。 /// </summary> /// <param name="address"></param> /// <returns></returns> protected override WebRequest GetWebRequest(Uri address) { WebRequest request = base.GetWebRequest(address); if (request is HttpWebRequest) { HttpWebRequest httpRequest = request as HttpWebRequest; httpRequest.CookieContainer = cookieContainer; } return request; } }
有WebClient DownloadData,比较大的数据页面可以使用它下载,比Request请求快多了。
支持Cookie修改,域名重定向,富媒体表单,异步请求,事件完成。做个58同城登录分分钟的事情
HttpTooler tooler = new HttpTooler(); tooler.RequestCompleted = OnRequestCompleted; tooler.GetHtml(RequestType.WebRequest, "www.58.com"); void OnRequestCompleted(object sender, string html) { //参数html 就是返回的结果 // do you want... }
that's all enjoy...