C# 模拟 Http 请求

1.支持 Gzip 和 deflate 压缩方式的响应信息

2.POST 可扩展提交文件

3.可设置代理(未测试过)

4.自动判断响应内容的字符集(简单判断,真实情况很复杂,有些无字符集描述的,或者 Response.Charset 是 ISO-**** 页面是 UTF-8 输出是 GBK ,环境很复杂,只能做到初步判断与转换)。


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

namespace System
{
    /// <summary>
    /// WebClient 请求工具类
    /// </summary>
    public static class HttpHelperV1
    {
        /// <summary>
        /// 浏览器标识
        /// 0:手机,1:IE
        /// </summary>
        public const string[] UserAgents = { 
"Mozilla/5.0(Linux;U;Android4.1.1;MI 2S Build/JRO03L)AppleWebKit/534.30 (KHTML,like Gecko)Version/4.0 Mobile Safari/534.30 XiaoMi/MiuiBrowser/1.0",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
                                            };
        #region POST

        /// <summary>
        /// 发送 POST 请求,并获取响应对象
        /// </summary>
        /// <param name="url">URL</param>
        /// <param name="UseAgent">浏览器标识</param>
        /// <param name="body">POST数据主体</param>
        /// <param name="head">头部信息</param>
        /// <param name="Proxy">代理信息</param>
        /// <returns></returns>
        public static HttpWebResponse PostAndGetResponse(string url, string UseAgent, byte[] body, Dictionary<string, string> head, IWebProxy Proxy)
        {
            HttpWebRequest Request = CreateRequest(url, head, UseAgent, Proxy);
            Request.Method = "POST";

            #region 设置主体

            if (body != null)
            {
                Request.ContentLength = body.Length;
                if (Request.ContentLength > 0)
                {
                    using (var requestStream = Request.GetRequestStream())
                    {
                        requestStream.Write(body, 0, body.Length);
                        requestStream.Close();
                    }
                }
            }
            else Request.ContentLength = 0;

            #endregion

            return (HttpWebResponse)Request.GetResponse();
        }
        /// <summary>
        /// 发送 POST 请求,并获取响应流
        /// </summary>
        /// <param name="url">URL</param>
        /// <param name="UseAgent">浏览器标识</param>
        /// <param name="param">参数</param>
        /// <param name="head">头部信息</param>
        /// <param name="Proxy">代理信息</param>
        /// <returns></returns>
        public static Stream PostAndGetStream(string url, string UseAgent, Dictionary<string, string> param, Dictionary<string, string> head, IWebProxy Proxy)
        {
            return PostAndGetResponse(url, UseAgent, Encoding.UTF8.GetBytes(param.paramToURL()), head, Proxy).GetStream();
        }
        /// <summary>
        /// 发送 POST 请求,并获取响应的 string 值
        /// </summary>
        /// <param name="url">URL</param>
        /// <param name="UseAgent">浏览器标识</param>
        /// <param name="param">参数</param>
        /// <param name="head">头部信息</param>
        /// <param name="Proxy">代理信息</param>
        /// <returns></returns>
        public static string PostAndGetString(string url, string UseAgent, Dictionary<string, string> param, Dictionary<string, string> head, IWebProxy Proxy)
        {
            return PostAndGetResponse(url, UseAgent, Encoding.UTF8.GetBytes(param.paramToURL()), head, Proxy).GetString();
        }

        #endregion

        #region GET

        /// <summary>
        /// 发送 GET 请求并获取响应对象
        /// </summary>
        /// <param name="url">URL</param>
        /// <param name="UseAgent">浏览器标识</param>
        /// <param name="head">头部信息</param>
        /// <param name="Proxy">代理信息</param>
        /// <returns></returns>
        public static HttpWebResponse GetAndGetResponse(string url, string UseAgent, Dictionary<string, string> head, IWebProxy Proxy)
        {
            //创建请求对象
            HttpWebRequest Request = CreateRequest(url, head, UseAgent, Proxy);
            //设置请求的发送为 GET 形式
            Request.Method = "GET";
            //返回响应对象
            return (HttpWebResponse)Request.GetResponse();
        }
        /// <summary>
        /// 发送 GET 请求,并获取响应的 string 值
        /// </summary>
        /// <param name="url">请求的URL</param>
        /// <param name="UseAgent">浏览器标识</param>
        /// <param name="param">发送的参数</param>
        /// <param name="head">发送的头部</param>
        /// <param name="Proxy">代理信息</param>
        /// <returns></returns>
        public static String GetAndGetString(string url, string UseAgent, Dictionary<string, string> param, Dictionary<string, string> head, IWebProxy Proxy)
        {
            return GetAndGetResponse(param.ParamInsertToURL(url), UseAgent, head, Proxy).GetString();
        }
        /// <summary>
        /// 发送 GET 请求,并获取响应的流
        /// </summary>
        /// <param name="url">请求的URL</param>
        /// <param name="UseAgent">浏览器标识</param>
        /// <param name="param">发送的参数</param>
        /// <param name="head">发送的头部</param>
        /// <param name="Proxy">代理信息</param>
        /// <returns></returns>
        public static Stream GetAndGetStream(string url, string UseAgent, Dictionary<string, string> param, Dictionary<string, string> head, IWebProxy Proxy)
        {
            return GetAndGetResponse(param.ParamInsertToURL(url), UseAgent, head, Proxy).GetStream();
        }

        #endregion

        #region 通用函数

        /// <summary>
        /// 获取响应流的副本
        /// </summary>
        /// <param name="Response"></param>
        /// <returns></returns>
        public static Stream GetStream(this HttpWebResponse Response)
        {
            //将响应流复制到结果流里返回给函数
            Stream result = new MemoryStream();
            Response.GetResponseStream().CopyTo(result);
            result.Position = 0;
            return result;
        }
        /// <summary>
        /// 将响应流转换成 String
        /// 自动处理字符集转换问题(简单转换)
        /// </summary>
        /// <param name="Response"></param>
        /// <returns></returns>
        public static string GetString(this HttpWebResponse Response)
        {
            string result = null;
            //设置副本流
            using (Stream responseStream = new MemoryStream())
            {
                //将响应流复制到副本流
                Response.GetResponseStream().CopyTo(responseStream);
                //设置默认字符集名称
                string encodStr = string.IsNullOrEmpty(Response.CharacterSet) ? "UTF-8" : Response.CharacterSet;
                
                bool isReadHtmlCharset = false; //已读取 html 中的字符集名称


            ReadStream: //读取流锚点
                responseStream.Position = 0;                        //将副本流的起始位置设为原点
                Encoding encoding = Encoding.GetEncoding(encodStr); //设置读取字符集
                using (MemoryStream tmp = new MemoryStream())       //设置临时流
                {
                    responseStream.CopyTo(tmp);                     //将副本流复制到临时流
                    tmp.Position = 0;                               //设置临时流的起始位置为原点
                    //按照设定的字符集读取临时流
                    using (var StreamReader = new StreamReader(tmp, encoding))
                    {
                        result = StreamReader.ReadToEnd();          //读取全部字符串
                    }
                }
                //若没从结果里面读取过 html 的 charset 的,就执行
                if (!isReadHtmlCharset)
                {
                    //将 html 多余的空格、换行、制表符等 \s 符号通通替换为一个空格,并转换成小写。
                    string regexSource = Regex.Replace(result, "\\s+", " ").ToLower(); //正则拼配源
                    
                    //正则表达式, 获取html上的字符集名称
                    string[] regexStrs = new string[] 
                        {                             
                        "<meta charset=\\s?[\"]?\\s?(?<charset>([\\w\\-]+))\\s?[\"]?\\s?[\\/]?>",
                        "<meta http-equiv=\\s?[\"]?\\s?content-type\\s?[\"]?\\s? content=\\s?[\"]?\\s?text/html; charset=(?<charset>([\\w\\-]*))\\s?[\"]?\\s?[\\/]?>"
                        };

                    foreach (var regexStr in regexStrs)
                    {
                        //获取匹配项
                        var match = Regex.Match(regexSource, regexStr);
                        if (match.Success) //成功匹配
                        {
                            //获取字符集名称
                            string tmp = match.Groups["charset"].Value;
                            if (!string.IsNullOrEmpty(tmp)) //字符集名称有具体数值
                            {
                                //构建异常处理,防止页面上的字符集名称不规范引发的异常
                                try
                                {
                                    //获取页面上字符集
                                    Encoding tmpEncoding = Encoding.GetEncoding(tmp);

                                    //若页面的字符集跟响应流的字符集不一致,则将字符集改成
                                    //页面字符集,重新读取一次 html
                                    if (tmpEncoding.EncodingName != encoding.EncodingName)
                                    {
                                        encodStr = tmp;
                                        isReadHtmlCharset = true;
                                        goto ReadStream; //返回读取流锚点再执行一次读取
                                    }
                                }
                                catch (Exception ex)
                                {

                                }
                            }
                        }
                    }

                }


            }
            return result;
        }
        /// <summary>
        /// 创建 Request
        /// </summary>
        /// <param name="url">完整的链接地址</param>
        /// <param name="head">头部信息</param>
        /// <param name="UserAgent">浏览器信息</param>
        /// <param name="proxy">代理</param>
        /// <returns></returns>
        public static HttpWebRequest CreateRequest(string url, Dictionary<string, string> head, string UserAgent, IWebProxy proxy)
        {
            //创建 Request 
            HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(url);
            Request.ContentType = "application/x-www-form-urlencoded";                                      //接受响应流的类型
            Request.Timeout = 60 * 1000;                                                                    //一分钟超时 
            Request.Proxy = proxy ?? Request.Proxy;                                                         //设置代理
            Request.UserAgent = UserAgent ?? UserAgents[1];                                                 //设置浏览器标识
            Request.Headers.Set("Accept-Encoding", "gzip, deflate");                                        //设置接受响应流的压缩方式
            Request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;      //设置自动解压方式
            

            #region 设置头部

            if (head != null && head.Count > 0)
            {
                foreach (var key in head.Keys)
                {
                    if (Request.Headers.AllKeys.Contains(key))
                        Request.Headers.Set(key, head[key]);
                }
            }

            #endregion

            return Request;
        }
        /// <summary>
        /// 将参数拼接到 URL 之后
        /// </summary>
        /// <param name="param"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        private static string ParamInsertToURL(this Dictionary<string, string> param, string url)
        {
            string result = url;
            //URL 与 param 都有值才进行处理,否则返回原 URL
            if (!string.IsNullOrEmpty(url) && param != null && param.Count > 0)
            {
                //判断中间拼接字符串选择,如果URL已带有参数,则用 & ,否则为 ?
                result = url + (url.Contains("?") ? "&" : "?") + param.paramToURL();
            }
            return url;
        }
        /// <summary>
        /// 键值对参数转成 URL 拼接字符串,Value 将做 UrlEncode 处理
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private static string paramToURL(this Dictionary<string, string> param)
        {
            string paramStr = string.Empty;
            //参数有值才处理,为空或无值就返回 string.Empty
            if (param != null && param.Count > 0)
            {
                //拼接参数
                //兼容 .net3.5-4.5 ,使用 Linq 扩展函数
                //范例:  "param1=456¶m2=test¶m3=%2094"
                paramStr = string.Join("&", param.Select(s => string.Format("{0}={1}", s.Key, HttpUtility.UrlEncode(s.Value))).ToArray());
            }
            return paramStr;
        }

        #endregion
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值