HttpClient类

 /// <summary>
    /// http 同步请求类
    /// 如果类库中没有提供设置HttpWebRequest参数的方法,可以实现OnCreatedRequest回调,自己再去设置
    /// 有任何错误可以判断Exception类型,获取相应错误信息
    /// </summary>
    public class HttpClient
    {
        private Encoding respEncoding = Encoding.UTF8;

#if DEBUG
        private int timeout = Int32.MaxValue;
#else
        private int timeout = 30000;
#endif
        
        /// <summary>
        /// 字符编码
        /// </summary>
        public Encoding DefaultEncoding { get; set; } = Encoding.UTF8;

        /// <summary>
        /// 当HttpWebRequest创建完成回调
        /// </summary>
        public Action<HttpWebRequest> OnCreatedRequest { get; set; }
        
        /// <summary>
        /// 设置超时时间,默认30秒,单位毫秒
        /// </summary>
        /// <param name="timeout"></param>
        public void SetTimeout(int timeout)
        {
            this.timeout = timeout;
        }
        
        /// <summary>
        /// 请求报文头
        /// </summary>
        public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();

        /// <summary>
        /// 异常信息
        /// </summary>
        public Exception Exception { get; set; }

        /// <summary>
        /// HttpStatusCode
        /// </summary>
        public HttpStatusCode HttpStatusCode { get; set; }



        /// <summary>
        /// 同步Get
        /// </summary>
        /// <param name="url">路径</param>
        /// <returns>返回</returns>
        public string Get(string url)
        {
            var httpWebRequest = CreateHttpWebRequest(url);
            httpWebRequest.Method = "GET";

            //返回数据s
            var bytes = GetRespBytes(httpWebRequest);
            return bytes != null ? respEncoding.GetString(bytes) : null;
        }
        
        /// <summary>
        /// 同步post
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="postStr">数据</param>
        /// <param name="isjson">是否是json数据,默认false</param>
        /// <returns>返回</returns>
        public string Post(string url, string postStr = null, bool isjson = false)
        {
            return Post(url, string.IsNullOrEmpty(postStr) ? null : DefaultEncoding.GetBytes(postStr), isjson);
        }
        
        /// <summary>
        /// 同步post
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="contentBytes">内容的byte字节</param>
        /// <param name="isjson">是否是json数据,默认false</param>
        /// <returns>返回</returns>
        public string Post(string url, byte[] contentBytes = null, bool isjson = false)
        {
            HttpWebRequest httpWebRequest = CreateHttpWebRequest(url, isjson);
            httpWebRequest.Method = "POST";

            //写数据
            if (contentBytes != null && contentBytes.Length > 0)
            {
                httpWebRequest.ContentLength = contentBytes.Length;
                try
                {
                    using (var myStream = httpWebRequest.GetRequestStream())
                    {
                        myStream.Write(contentBytes, 0, contentBytes.Length);
                    }
                }
                catch (Exception ex)
                {
                    Exception = ex;
                    return null;
                }
            }
            //返回数据
            var bytes = GetRespBytes(httpWebRequest);
            return bytes != null ? respEncoding.GetString(bytes) : null;
        }

        /// <summary>
        /// 获取返回数据
        /// </summary>
        /// <param name="httpWebRequest"></param>
        /// <returns>返回</returns>
        private byte[] GetRespBytes(HttpWebRequest httpWebRequest)
        {
            //接收数据
            using (HttpWebResponse httpResp = GetHttpWebResponse(httpWebRequest))
            {
                Stream respStream = httpResp?.GetResponseStream();
                if (respStream == null) return null;
                using (Stream stream = httpResp.ContentEncoding.ToLower().Contains("gzip")
                    ? new GZipStream(respStream, CompressionMode.Decompress)
                    : respStream)
                {
                    List<byte> lst = new List<byte>();
                    int nRead;
                    while ((nRead = stream.ReadByte()) != -1) lst.Add((byte)nRead);

                    var bytes = lst.ToArray();
                    //获取编码
                    respEncoding = GetHtmlEncoding(httpResp, bytes);
                    return bytes;
                }
            }
        }


        /// <summary>
        /// 创建HttpWebRequest
        /// </summary>
        /// <param name="url">url地址</param>
        /// <param name="isjson">是否是json数据,默认false</param>
        /// <returns>返回</returns>
        private HttpWebRequest CreateHttpWebRequest(string url, bool isjson = false)
        {
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
            HttpStatusCode = HttpStatusCode.Created;
            httpWebRequest.Accept = "text/html, application/xhtml+xml, */*";
            httpWebRequest.ContentType = "application/x-www-form-urlencoded;charset=" + DefaultEncoding.WebName;
            if (isjson)
                httpWebRequest.ContentType = "application/json;charset=" + DefaultEncoding.WebName;
            httpWebRequest.UserAgent = "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/7.0;)";
            //httpWebRequest.UserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C92 Safari/601.1 wechatdevtools/0.18.182200 MicroMessenger/6.5.7 Language/zh_CN webview/0)";
            httpWebRequest.ProtocolVersion = HttpVersion.Version11;
            httpWebRequest.Headers.Add("Accept-Language", "zh-cn");
            httpWebRequest.Headers.Add("Accept-Encoding", "gzip, deflate");
            httpWebRequest.Headers.Add("Pragma", "no-cache");
            httpWebRequest.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
            httpWebRequest.KeepAlive = true;
            //httpWebRequest.AllowAutoRedirect = true;
            httpWebRequest.ServicePoint.Expect100Continue = false;
            httpWebRequest.Timeout = timeout;

            //添加header
            if (Headers.Count > 0)
            {
                foreach (var header in Headers)
                    httpWebRequest.Headers.Add(header.Key, header.Value);
            }

            if (url.Contains("https://"))
                SetCertificatePolicy();

            OnCreatedRequest?.Invoke(httpWebRequest);
            return httpWebRequest;
        }

        /// <summary>
        /// 获取HttpWebResponse
        /// </summary>
        /// <param name="httpWebRequest"></param>
        /// <returns>返回</returns>
        private HttpWebResponse GetHttpWebResponse(HttpWebRequest httpWebRequest)
        {
            HttpWebResponse httpResp = null;
            try
            {
                httpResp = (HttpWebResponse)httpWebRequest.GetResponse();
                HttpStatusCode = httpResp.StatusCode;
            }
            catch (WebException ex)
            {
                Exception = ex;
                if (ex.Response != null)
                {
                    httpResp = (HttpWebResponse) ex.Response;
                    HttpStatusCode = httpResp.StatusCode;
                }
            }
            catch (Exception ex)
            {
                Exception = ex;
            }

            return httpResp;
        }

        /// <summary>
        /// 从html内容获取编码
        /// </summary>
        /// <param name="response"></param>
        /// <param name="bytes"></param>
        /// <returns>返回</returns>
        private Encoding GetHtmlEncoding(HttpWebResponse response, byte[] bytes)
        {
            Encoding encoding = DefaultEncoding;
            //检测响应头是否返回了编码类型,若返回了编码类型则使用返回的编码
            //注:有时响应头没有编码类型,CharacterSet经常设置为ISO-8859-1
            if (!string.IsNullOrEmpty(response.CharacterSet) && response.CharacterSet.ToUpper() != "ISO-8859-1")
            {
                encoding = Encoding.GetEncoding(response.CharacterSet == "utf8" ? "utf-8" : response.CharacterSet);
            }
            else
            {
                //若没有在响应头找到编码,则去html找meta头的charset
                var result = Encoding.Default.GetString(bytes);
                //在返回的html里使用正则匹配页面编码
                Match match = Regex.Match(result, @"<meta.*charset=""?([\w-]+)""?.*>", RegexOptions.IgnoreCase);
                if (match.Success)
                {
                    encoding = Encoding.GetEncoding(match.Groups[1].Value);
                }
            }
            return encoding;
        }
        
        /// <summary>
        /// 注册证书
        /// </summary>
        private void SetCertificatePolicy()
        {
            ServicePointManager.ServerCertificateValidationCallback
                       += RemoteCertificateValidate;
        }

        /// <summary>  
        /// 远程证书验证,固定返回true 
        /// </summary>  
        private bool RemoteCertificateValidate(object sender, X509Certificate cert,
            X509Chain chain, SslPolicyErrors error)
        {
            return true;
        }
    }

 

上一篇:Flutter代理设置


下一篇:Httpclient工具类封装