常用类-http请求

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;

namespace Net
{
    public class HttpUtil
    {
        private string accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*";
        private string userAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
        private HttpMethod method = HttpMethod.GET;
        private HttpContentType contentType = HttpContentType.Application_x_www_form_urlencoded;
        private bool keepAlive = true;
        private bool allowAutoRedirect = true;
        private bool expect100Continue = false;
        private string url = string.Empty;
        private string referer = string.Empty;
        private string cookieHeader = string.Empty;
        private readonly List<HttpPostData> postingData = new List<HttpPostData>();
        private int fileCount = 0;
        private bool addWWWToUrl = false;
        private int timeout = 100000;
        private bool hasMethodSet = false;

        public string RequestEncoding { get; set; }

        public string boundary { get; set; }
        public string MultipartFormData { get; set; }
        private Hashtable header = new Hashtable();

        /// <summary>
        /// 添加http标头
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void AddRequestHeader(string key, string value)
        {
            header.Add(key, value);
        }

        /// <summary>
        /// 构造新的HttpUtil实例
        /// </summary>
        /// <param name="url">请求的 Internet 资源的统一资源标识符</param>
        public HttpUtil(string url)
            : this(url, string.Empty, string.Empty)
        { }

        /// <summary>
        /// 构造新的HttpUtil实例
        /// </summary>
        /// <param name="url">请求的 Internet 资源的统一资源标识符</param>
        /// <param name="referer">Referer HTTP 标头的值</param>
        public HttpUtil(string url, string referer)
            : this(url, referer, string.Empty)
        { }

        /// <summary>
        /// 构造新的HttpUtil实例
        /// </summary>
        /// <param name="url">请求的 Internet 资源的统一资源标识符</param>
        /// <param name="referer">Referer HTTP 标头的值</param>
        /// <param name="cookieHeader">Cookie HTTP 标头的值</param>
        public HttpUtil(string url, string referer, string cookieHeader)
        {
            this.url = url;
            this.referer = referer;
            this.cookieHeader = cookieHeader;
        }

        /// <summary>
        /// 获取或设置 Accept HTTP 标头的值
        /// </summary>
        public string Accept
        {
            get { return accept; }
            set { accept = value; }
        }

        /// <summary>
        /// 获取或设置 User-agent HTTP 标头的值
        /// </summary>
        public string UserAgent
        {
            get { return userAgent; }
            set { userAgent = value; }
        }

        /// <summary>
        /// 获取或设置请求的方法(Get请求还是Post请求)
        /// </summary>
        public HttpMethod Method
        {
            get { return method; }
            set
            {
                method = value;
                hasMethodSet = true;
            }
        }

        /// <summary>
        /// 获取或设置 Content-type HTTP 标头的值
        /// </summary>
        public HttpContentType ContentType
        {
            get { return contentType; }
            set { contentType = value; }
        }

        /// <summary>
        /// 获取或设置一个值,该值指示是否与 Internet 资源建立持久性连接
        /// </summary>
        public bool KeepAlive
        {
            get { return keepAlive; }
            set { keepAlive = value; }
        }

        /// <summary>
        /// 获取或设置一个值,该值指示请求是否应跟随重定向响应
        /// </summary>
        public bool AllowAutoRedirect
        {
            get { return allowAutoRedirect; }
            set { allowAutoRedirect = value; }
        }

        /// <summary>
        /// 获取或设置是否使用 100-Continue 行为
        /// </summary>
        public bool Expect100Continue
        {
            get { return expect100Continue; }
            set { expect100Continue = value; }
        }

        /// <summary>
        /// 获取或设置请求超时前等待的毫秒数。
        /// </summary>
        public int TimeOut
        {
            get { return timeout; }
            set { timeout = value; }
        }


        /// <summary>
        /// 获取或设置实际响应请求的 Internet 资源的统一资源标识符
        /// </summary>
        public string Url
        {
            get { return url; }
            set { url = value; }
        }

        /// <summary>
        /// 获取或设置 Referer HTTP 标头的值
        /// </summary>
        public string Referer
        {
            get { return referer; }
            set { referer = value; }
        }

        /// <summary>
        /// 获取或设置 Cookie HTTP 标头的值
        /// </summary>
        public string CookieHeader
        {
            get { return cookieHeader; }
            set { cookieHeader = value; }
        }

        /// <summary>
        /// 获取或设置Url是否补上www
        /// </summary>
        public bool AddWWWToUrl
        {
            get { return addWWWToUrl; }
            set { addWWWToUrl = value; }
        }
        /// <summary>
        /// 要上传的文件.如果不为空则自动转为Post请求
        /// </summary>
        public List<HttpPostData> Files
        {
            get
            {
                List<HttpPostData> files = new List<HttpPostData>();
                foreach (HttpPostData file in postingData)
                {
                    if (file.IsFile)
                        files.Add(file);
                }
                return files;
            }
        }

        /// <summary>
        /// 要发送的Form表单信息
        /// </summary>
        public List<HttpPostData> PostingData
        {
            get
            {
                List<HttpPostData> data = new List<HttpPostData>();
                foreach (HttpPostData dt in postingData)
                {
                    if (!dt.IsFile)
                        data.Add(dt);
                }
                return data;
            }
        }

        /// <summary>
        /// 在请求中添加要上传的文件
        /// </summary>
        /// <param name="fieldName">文件字段的名称</param>
        /// <param name="fileName">要上传的文件完整路径</param>
        public void AttachFile(string fieldName, string fileName)
        {
            HttpPostData file = new HttpPostData(fieldName, fileName, true);
            postingData.Add(file);
            fileCount++;
        }

        /// <summary>
        /// 在请求中添加要上传的数据
        /// </summary>
        /// <param name="fieldName">普通字段的名称</param>
        /// <param name="fieldValue">普通字段的值</param>
        public void AddPostData(string fieldName, string fieldValue)
        {
            HttpPostData data = new HttpPostData(fieldName, fieldValue, false);
            postingData.Add(data);
        }

        public void AddPostData(string data)
        {
            AddPostData(string.Empty, data);
        }

        public long ContentLength { get; set; }

        private HttpWebRequest CreateRequest()
        {
            string newLine = "\r\n";
            string boundary = "---------------------------7d81961530944";
            if (!hasMethodSet)
            {
                if (postingData.Count > 0)
                {
                    method = HttpMethod.POST;
                }
                else
                {
                    method = HttpMethod.GET;
                }
            }

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);

            req.Timeout = timeout;
            req.Method = method.ToString();
            req.KeepAlive = keepAlive;
            req.AllowAutoRedirect = allowAutoRedirect;
            req.Accept = accept;
            req.UserAgent = userAgent;
            req.Referer = referer;
            req.ServicePoint.Expect100Continue = expect100Continue;
            req.CookieContainer = new CookieContainer();

            foreach (var s in header.Keys)
            {
                req.Headers.Add(s.ToString(), header[s].ToString());
            }

            if (cookieHeader.Length > 0)
            {
                cookieHeader = cookieHeader.Replace("$", "");
                string cookievalue = cookieHeader.Replace("; ", ",");
                req.CookieContainer.SetCookies(new Uri("http://" + req.RequestUri.Host), cookievalue);
            }


            if (method == HttpMethod.POST || method == HttpMethod.PUT)
            {
                if (fileCount > 0)
                    contentType = HttpContentType.Multipart_form_data;

                if (contentType == HttpContentType.Application_x_www_form_urlencoded)
                {
                    req.ContentType = "application/x-www-form-urlencoded";
                }
                else if (contentType == HttpContentType.Multipart_form_data)
                {
                    req.ContentType = "multipart/form-data; boundary=" + boundary;
                }
                else if (contentType == HttpContentType.Text_xml)
                {
                    req.ContentType = "text/xml";
                }
                else if (contentType == HttpContentType.Application_xml)
                {
                    req.ContentType = "application/xml";
                }
                else if (contentType == HttpContentType.application_json)
                {
                    req.ContentType = "multipart/form-data; boundary=qeguwjqpcikhukevtqcuivtjcuvbbyfn";
                }


                Stream stream = req.GetRequestStream();

                StreamWriter streamWriter = null;

                if (RequestEncoding == null)
                {
                    streamWriter = new StreamWriter(stream, Encoding.GetEncoding(437));
                }
                else
                {
                    streamWriter = new StreamWriter(stream, Encoding.GetEncoding(RequestEncoding));
                }

                if (contentType != HttpContentType.Multipart_form_data)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (HttpPostData data in postingData)
                    {
                        if (data.FieldName.Length > 0)
                        {
                            sb.AppendFormat("{0}={1}&", data.FieldName, data.FieldValue);
                        }
                        else
                        {
                            //适用于Amazon上传Inventory
                            sb.AppendFormat("{0}&", data.FieldValue);
                        }
                    }
                    if (sb.Length > 0)
                    {
                        sb.Length--;
                        streamWriter.Write(sb.ToString());
                    }
                }
                else
                {
                    foreach (HttpPostData data in postingData)
                    {
                        if (!data.IsFile)
                        {
                            streamWriter.Write("--" + boundary + newLine);
                            streamWriter.Write("Content-Disposition: form-data; name=\"{0}\"{1}{1}", data.FieldName, newLine);
                            streamWriter.Write(data.FieldValue + newLine);
                        }
                        else
                        {
                            if (!string.IsNullOrEmpty(data.FieldValue) && File.Exists(data.FieldValue))
                            {
                                string extension = (new FileInfo(data.FieldValue)).Extension;
                                if (extension.ToLower() != "gif")
                                    extension = "pjpeg";

                                streamWriter.Write("--" + boundary + newLine);
                                streamWriter.Write(
                                    "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}",
                                    data.FieldName,
                                    data.FieldValue,
                                    newLine
                                    );
                                streamWriter.Write("Content-Type: image/" + extension + newLine + newLine);

                                streamWriter.Flush();

                                FileStream fs = null;
                                try
                                {
                                    fs = new FileStream(data.FieldValue, FileMode.Open, FileAccess.Read, FileShare.Read);
                                    byte[] bytes = new byte[1024];
                                    while (fs.CanRead)
                                    {
                                        int read = fs.Read(bytes, 0, 1024);

                                        stream.Write(bytes, 0, read);
                                        if (read == 0)
                                        {
                                            break;
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    throw ex;
                                }
                                finally
                                {
                                    fs.Close();
                                }

                                stream.Flush();
                                streamWriter.Write(newLine);
                            }
                            else
                            {
                                streamWriter.Write("--" + boundary + newLine);
                                streamWriter.Write(
                                    "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}",
                                    data.FieldName,
                                   "",
                                    newLine
                                    );
                                streamWriter.Write("Content-Type: application/octet-stream" + newLine + newLine + newLine);
                            }
                        }
                    }
                    streamWriter.Write("--" + boundary + "--" + newLine);
                }

                streamWriter.Close();
                stream.Close();
            }
            return req;
        }


        private HttpWebRequest CreateRequestData()
        {
            string newLine = "\r\n";
            if (string.IsNullOrEmpty(this.boundary))
            {
                boundary = "----WebKitFormBoundaryrCnAdKfNQAfXw6iY";
            }

            if (!hasMethodSet)
            {
                if (postingData.Count > 0)
                {
                    method = HttpMethod.POST;
                }
                else
                {
                    method = HttpMethod.GET;
                }
            }

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);

            req.Timeout = timeout;
            req.Method = method.ToString();
            req.KeepAlive = keepAlive;
            req.AllowAutoRedirect = allowAutoRedirect;
            req.Accept = accept;
            req.UserAgent = userAgent;
            req.Referer = referer;
            req.ServicePoint.Expect100Continue = expect100Continue;
            req.CookieContainer = new CookieContainer();

            foreach (var s in header.Keys)
            {
                req.Headers.Add(s.ToString(), header[s].ToString());
            }

            if (cookieHeader.Length > 0)
            {
                cookieHeader = cookieHeader.Replace("$", "");
                string cookievalue = cookieHeader.Replace("; ", ",");
                req.CookieContainer.SetCookies(new Uri("http://" + req.RequestUri.Host), cookievalue);
            }


            if (method == HttpMethod.POST || method == HttpMethod.PUT)
            {
                if (fileCount > 0)
                    contentType = HttpContentType.Multipart_form_data;

                if (contentType == HttpContentType.Application_x_www_form_urlencoded)
                {
                    req.ContentType = "application/x-www-form-urlencoded";
                }
                else if (contentType == HttpContentType.Multipart_form_data)
                {
                    req.ContentType = "multipart/form-data; boundary=" + boundary;
                }
                else if (contentType == HttpContentType.Text_xml)
                {
                    req.ContentType = "text/xml";
                }
                else if (contentType == HttpContentType.Application_xml)
                {
                    req.ContentType = "application/xml";
                }
                else if (contentType == HttpContentType.application_json)
                {
                    req.ContentType = "multipart/form-data; boundary=qeguwjqpcikhukevtqcuivtjcuvbbyfn";
                }


                Stream stream = req.GetRequestStream();

                StreamWriter streamWriter = null;

                if (RequestEncoding == null)
                {
                    streamWriter = new StreamWriter(stream, Encoding.GetEncoding(437));
                }
                else
                {
                    streamWriter = new StreamWriter(stream, Encoding.GetEncoding(RequestEncoding));
                }

                if (contentType != HttpContentType.Multipart_form_data)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (HttpPostData data in postingData)
                    {
                        if (data.FieldName.Length > 0)
                        {
                            sb.AppendFormat("{0}={1}&", data.FieldName, data.FieldValue);
                        }
                        else
                        {
                            //适用于Amazon上传Inventory
                            sb.AppendFormat("{0}&", data.FieldValue);
                        }
                    }
                    if (sb.Length > 0)
                    {
                        sb.Length--;
                        streamWriter.Write(sb.ToString());
                    }
                }
                else
                {
                    foreach (HttpPostData data in postingData)
                    {
                        if (!data.IsFile)
                        {
                            streamWriter.Write("--" + boundary + newLine);
                            streamWriter.Write("Content-Disposition: form-data; name=\"{0}\"{1}{1}", data.FieldName, newLine);
                            streamWriter.Write(data.FieldValue + newLine);
                        }
                        else
                        {
                            if (!string.IsNullOrEmpty(data.FieldValue) && File.Exists(data.FieldValue))
                            {

                                streamWriter.Write(MultipartFormData);
                                streamWriter.Flush();

                                FileStream fs = null;
                                try
                                {
                                    fs = new FileStream(data.FieldValue, FileMode.Open, FileAccess.Read, FileShare.Read);
                                    byte[] bytes = new byte[1024];
                                    while (fs.CanRead)
                                    {
                                        int read = fs.Read(bytes, 0, 1024);

                                        stream.Write(bytes, 0, read);
                                        if (read == 0)
                                        {
                                            break;
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    throw ex;
                                }
                                finally
                                {
                                    fs.Close();
                                }

                                stream.Flush();
                                streamWriter.Write(newLine);
                            }
                            else
                            {
                                streamWriter.Write("--" + boundary + newLine);
                                streamWriter.Write(
                                    "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}",
                                    data.FieldName,
                                   "",
                                    newLine
                                    );
                                streamWriter.Write("Content-Type: application/octet-stream" + newLine + newLine + newLine);
                            }
                        }
                    }
                    streamWriter.Write("--" + boundary + "--" + newLine);
                }

                streamWriter.Close();
                stream.Close();
            }
            return req;
        }

        /// <summary>
        /// 清空Post的数据,并把Method设置为Get
        /// 在发出一个包含上述信息的请求后,必须调用此方法或手工设置相应属性以使下一次请求不会受到影响
        /// </summary>
        private void Reset()
        {
            method = HttpMethod.GET;
            contentType = HttpContentType.Application_x_www_form_urlencoded;
            keepAlive = true;
            allowAutoRedirect = true;
            expect100Continue = false;
            addWWWToUrl = false;
            fileCount = 0;
            timeout = 150000;
            postingData.Clear();
            header.Clear();
            hasMethodSet = false;
        }

        public HttpWebResponse GetResponse()
        {
            return GetResponse(false);
        }


        /// <summary>
        /// 发出一次新的请求,并返回获得的回应
        /// </summary>
        /// <returns>相应的HttpWebResponse</returns>
        public HttpWebResponse GetResponse(bool specialCookie)
        {
            
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
            HttpWebRequest req = null;
            if (!string.IsNullOrEmpty(this.MultipartFormData))
            {
                req = CreateRequestData();
            }
            else
            {
               
                req = CreateRequest();
            }
           
            HttpWebResponse rep;
            try
            {
                ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
                rep = (HttpWebResponse)req.GetResponse();
            }
            catch (WebException ex)
            {
                rep = (HttpWebResponse)ex.Response;
                if (rep == null)
                    throw ex;
            }

            string myCookies = string.Empty;
            if (!addWWWToUrl)
            {
                myCookies = req.CookieContainer.GetCookieHeader(req.RequestUri);
            }
            else
            {
                string reqUrl = req.RequestUri.OriginalString;
                int pos = reqUrl.IndexOf("//");
                myCookies = req.CookieContainer.GetCookieHeader(new Uri(reqUrl.Substring(0, pos + 2) + "www." + reqUrl.Substring(pos + 2)));
            }

            cookieHeader = myCookies;

            if (specialCookie)
            {
                CookieContainer contain = req.CookieContainer;

                myCookies = rep.Headers["Set-cookie"];
                string myCookiesCopy = myCookies;
                if (!string.IsNullOrEmpty(myCookies))
                {
                    //Regex re = new Regex("([^;,]+)=([^;,]+);Domain=([^;,]+);Path=([^;,]+)", RegexOptions.IgnoreCase);
                    Regex re = new Regex("([^;,]+)=([^;,]+);", RegexOptions.IgnoreCase);
                    MatchCollection mc = re.Matches(myCookies);
                    myCookies = cookieHeader;
                    foreach (Match m in mc)
                    {
                        //name,   value,   path,   domain  
                        string name = m.Groups[1].Value.Trim();
                        string value = m.Groups[2].Value;
                        if (name.ToLower() != "domain" && name.ToLower() != "path" && name.ToLower() != "expires")
                        {
                            //用户的电脑时钟大于服务器的时钟造成设置cookie直接失效,而php在设置cookie失效时会对内容增加deleted这个值
                            //例如在facebook中会导致图片无法正确提交
                            if (value.ToLower() != "deleted")
                            {
                                //查找过期时间,由于.net自带的方法在处理“, ”上有问题,只好自己来写
                                Match mc2 = Regex.Match(myCookiesCopy, name + "[^,]+expires=([^;]+)");
                                if (mc2.Success)
                                {
                                    string expires = string.Empty;
                                    expires = mc2.Groups[1].Value;
                                    Match mc3 = Regex.Match(expires, ",[^,]+=");
                                    if (mc3.Success)
                                    {
                                        expires = expires.Substring(0, mc3.Index);
                                    }

                                    if (expires.Length > 0)
                                    {
                                        DateTime expireDate;
                                        if (DateTime.TryParse(expires, out expireDate))
                                        {
                                            if (expireDate < DateTime.Now)
                                                continue;
                                        }
                                    }
                                }

                                if (myCookies.IndexOf(name + "=", StringComparison.InvariantCultureIgnoreCase) > -1)
                                {
                                    myCookies = Regex.Replace(myCookies, name + "=[^;]+", name + "=" + value, RegexOptions.IgnoreCase);
                                }
                                else
                                {
                                    myCookies = myCookies + (myCookies.Length > 0 ? "; " + name + "=" + value : name + "=" + value);
                                }
                            }
                        }
                    }
                    cookieHeader = myCookies;
                }
            }

            referer = url;
            Reset();
            return rep;
        }

        /// <summary>
        /// 发出一次新的请求,并返回获得的回应
        /// </summary>
        /// <returns>请求页面的HTML代码</returns>
        public string GetHTMLString(bool specialCookie)
        {
            HttpWebResponse rep = GetResponse(specialCookie);
            Stream responseStream = rep.GetResponseStream();
            StreamReader responseReader = new StreamReader(responseStream, GetEncodingFromResponse(rep));
            string html = responseReader.ReadToEnd();
            responseReader.Close();
            rep.Close();
            return html;
        }


        public string GetGzipHTMLString(bool specialCookie)
        {
            HttpWebResponse rep = GetResponse(specialCookie);
            Stream responseStream = rep.GetResponseStream();
            //StreamReader responseReader = new StreamReader(responseStream, GetEncodingFromResponse(rep));
            //string html = responseReader.ReadToEnd();
            //responseReader.Close();

            string html = "";
            using (var zipStream = new System.IO.Compression.GZipStream(responseStream, System.IO.Compression.CompressionMode.Decompress))
            {

                using (StreamReader sr = new System.IO.StreamReader(zipStream, Encoding.UTF8))
                {
                    html = sr.ReadToEnd();
                }

            }

            rep.Close();
            return html;
        }

        public string GetHTMLString()
        {
            return GetHTMLString(false);
        }

        /// <summary>
        /// 根据已有的HttpWebResponse返回获得的回应
        /// </summary>
        /// <param name="rep">已有的HttpWebResponse</param>
        /// <returns>请求页面的HTML代码</returns>
        public string GetHTMLString(HttpWebResponse rep)
        {
            Stream responseStream = rep.GetResponseStream();
            StreamReader responseReader = new StreamReader(responseStream, GetEncodingFromResponse(rep));
            string html = responseReader.ReadToEnd();
            return html;
        }

        /// <summary>
        /// 根据http应答的http头来判断编码
        /// </summary>
        /// <param name="rep">产生的HttpWebResponse</param>
        /// <returns></returns>
        private Encoding GetEncodingFromResponse(HttpWebResponse rep)
        {
            Encoding encode = Encoding.Default;
            string characterSet = rep.CharacterSet;
            if (!string.IsNullOrEmpty(characterSet))
            {
                if (characterSet.IndexOf("ISO-8859-1", StringComparison.InvariantCultureIgnoreCase) > -1)
                {
                    characterSet = "gb2312";
                }
                else if (characterSet.IndexOf("UTF-8", StringComparison.InvariantCultureIgnoreCase) > -1)
                {
                    characterSet = "UTF-8";
                }
                encode = Encoding.GetEncoding(characterSet);
            }

            return encode;
        }
    }
    public enum HttpMethod
    {
        GET,
        POST,
        PUT,
        DELETE,
        PATCH
    }

    public enum HttpContentType
    {
        Application_x_www_form_urlencoded,
        Multipart_form_data,
        Text_xml,    //适用于Amazon上传Inventory
        Application_xml,
        application_json
    }

    public class HttpPostData
    {
        private string fieldName;
        private string fieldValue;
        private bool isFile;

        public string FieldName
        {
            get { return fieldName; }
            set { fieldName = value; }
        }

        public string FieldValue
        {
            get { return fieldValue; }
            set { fieldValue = value; }
        }

        public bool IsFile
        {
            get { return isFile; }
            set { isFile = value; }
        }

        public HttpPostData(string fieldName, string fieldValue, bool isFile)
        {
            this.fieldName = fieldName;
            this.fieldValue = fieldValue;
            this.isFile = isFile;
        }

        public override string ToString()
        {
            return FieldName + " : " + FieldValue;
        }
    }
}

  

posted @ 2019-03-19 22:11  毛毛球的书签  阅读(118)  评论(0编辑  收藏  举报