自己封装的HttpRequest,个人觉的比较HttpHelper好用

新年开篇,忙归忙,还是要写点什么,不然越来越懒,分享我写的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...

posted @ 2016-02-16 13:05  Kurodo  阅读(1800)  评论(1编辑  收藏  举报