Http协议操作类(优化版)
using Microsoft.VisualBasic; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Net; using System.Text; using System.IO; //HTTP协议操作:简化GET和POST请求,已针对C#优化Http连接创建时每个连接耗费时间长的问题以及多个连接并行时默认限制2个连接并行的问题,在多线程场景下更有效。 public class HttpProc{ private CookieCollection _cookieGet = new CookieCollection(); private CookieCollection _cookiePost = new CookieCollection(); private Encoding _encoding = System.Text.Encoding.Default; public IWebProxy _Proxy = null; private string _ResHtml; private string _strCode=""; private string _strErr=""; private string _strPostdata=""; private string _strRefUrl = ""; private string _strUrl=""; private string _StrUserAnget = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"; public System.Net.WebHeaderCollection Headers = new System.Net.WebHeaderCollection(); private int _timeout = 30000; private int _HttpCacheHours = 0; /// <summary> /// 设置相同URL响应内容是否要用于缓存的小时数,默认值为0,表示不使用Cache。 /// 使用Cache是为了减少对敏感URL的高频率调用。 /// </summary> public int HttpCacheHours { get { return _HttpCacheHours; } set { _HttpCacheHours = value; } } /// <summary> /// 获取或设置请求超时时间(毫秒) /// </summary> public int TimeOut { get { return this._timeout; } set { this._timeout = value; } } /// <summary> /// 获取或者设置使用的UserAgent /// </summary> /// <value></value> /// <returns></returns> /// <remarks>默认模拟Win2003平台、Ie6.0、.net CLR 1.1 </remarks> public string UserAgent { get { return _StrUserAnget; } set { _StrUserAnget = value; } } /// <summary> /// 获取或者设置当前要请求的地址 /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> public string strUrl { get { return this._strUrl; } set { this._strUrl = value; } } /// <summary> /// 获取或者设置发送时模拟的来源地址 /// </summary> /// <value></value> /// <returns></returns> /// <remarks>该属性应用在Http请求中的Referer标头</remarks> public string strRefUrl { get { return this._strRefUrl; } set { this._strRefUrl = value; } } /// <summary> /// 获取或者设置要发送的数据 /// </summary> /// <value></value> /// <returns></returns> /// <remarks>以Post方式发送的数据</remarks> public string strPostdata { get { return this._strPostdata; } set { this._strPostdata = value; } } /// <summary> /// 处理碰到的错误 /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> public string strErr { get { return this._strErr; } set { this._strErr = value; } } /// <summary> /// 获取得到的Http响应码 /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> public string strCode { get { return this._strCode; } } /// <summary> /// 获取响应的Http数据 /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> public string ResHtml { get { return this._ResHtml; } } /// <summary> /// 设置Http请求和响应中使用的编码 /// </summary> /// <value></value> /// <remarks></remarks> public Encoding encoding { get { return this._encoding; } set { this._encoding = value; } } /// <summary> /// 获取或者设置要发送的Cookie /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> public CookieCollection cookiePost { get { return this._cookiePost; } set { this._cookiePost = value; } } /// <summary> /// 获取响应中的Cookie /// </summary> /// <value></value> /// <returns></returns> /// <remarks></remarks> public CookieCollection cookieGet { get { return this._cookieGet; } } public string Method { get; set; } = "GET"; /// <summary> /// 处理Get和Post请求,得到相应 /// </summary> /// <returns></returns> /// <remarks>在设置好各个属性以后调用该方法;该方法只是简单的同步读取;该方法只考虑到Http响应的结果为文本</remarks> public string Proc() { //请求 HttpWebRequest HttRequest = null; //响应 HttpWebResponse HttpResponse = null; StreamReader sr = null; try { //从属性中创建Http请求 HttRequest = this.CreateRequest(); //从请求中创建响应 HttpResponse = (HttpWebResponse)HttRequest.GetResponse(); sr = new StreamReader(HttpResponse.GetResponseStream(), this.encoding); //直接读到结尾 this._ResHtml = sr.ReadToEnd(); //获取状态码 this._strCode = HttpResponse.StatusCode.ToString(); //如果状态码是302的话,设置返回的结果为新的地址 if ((object.ReferenceEquals(this._strCode, "302"))) { this._ResHtml = HttpResponse.Headers["location"]; } this.Headers.Add(HttpResponse.Headers); //如果有Cookie的话 //就获取Cookie if (HttpResponse.Cookies.Count > 0) { this._cookieGet = HttpResponse.Cookies; } } catch (Exception ex) { //错误 this._strErr = ex.Message+ex.StackTrace; _ResHtml = ""; } finally { //释放资源 if ((sr != null)) { sr.Close(); sr = null; } if ((HttpResponse != null)) { HttpResponse.Close(); HttpResponse = null; } if ((HttRequest != null)) { //HttRequest.Abort(); HttRequest = null; } } return this.ResHtml; } //以Multipart方式POST表单数据 public string PostMultipartForm(ArrayList Forms) { if (Forms == null) { return "Forms为空。"; } //防止该类之前post过数据'设置Nothing之后 _strPostdata = null; //边界 string _boundary = "-----------------------------7d6bb34502ce"; //请求 HttpWebRequest HttRequest = null; //响应 HttpWebResponse HttpResponse = null; StreamReader sr = null; try { //从属性中创建Http请求 HttRequest = this.CreateRequest(); //这里设置类型和边界 HttRequest.ContentType = "multipart/form-data; boundary=" + _boundary; HttRequest.Method = "POST"; //Post方式 //这里开始写上传的文件 StreamWriter sw = null; try { foreach (object ett in Forms) { if (ett is EntityForm) { //只处理正确的类型 //这里是可识别的 EntityForm etf = (EntityForm)ett; etf.boundary = _boundary; etf.WriteToStream(HttRequest.GetRequestStream()); } } sw = new StreamWriter(HttRequest.GetRequestStream(), encoding); //这些写最后的一个边界 sw.Write("--" + _boundary + "--"); //最后一个边界头和尾巴都附带2个-- sw.Write(Environment.NewLine); } catch (Exception ex) { } finally { if ((sw != null)) { sw.Close(); } } //从请求中创建响应 HttpResponse = (HttpWebResponse)HttRequest.GetResponse(); sr = new StreamReader(HttpResponse.GetResponseStream(), this.encoding); //直接读到结尾 this._ResHtml = sr.ReadToEnd(); //获取状态码 this._strCode = HttpResponse.StatusCode.ToString(); //如果状态码是302的话,设置返回的结果为新的地址 if ((object.ReferenceEquals(this._strCode, "302"))) { this._ResHtml = HttpResponse.Headers["location"]; } //如果有Cookie的话 //就获取Cookie if (HttpResponse.Cookies.Count > 0) { this._cookieGet = HttpResponse.Cookies; } } catch (Exception ex) { //错误 this._strErr = ex.Message; _ResHtml = ""; } finally { //释放资源 if ((sr != null)) { sr.Close(); sr = null; } if ((HttpResponse != null)) { HttpResponse.Close(); HttpResponse = null; } if ((HttRequest != null)) { HttRequest = null; } } return this.ResHtml; } public HttpWebRequest CreateRequest() { HttpWebRequest HttpRequest = null; HttpRequest = (HttpWebRequest)WebRequest.Create(this._strUrl); HttpRequest.Method = this.Method; HttpRequest.Accept = "*/*"; HttpRequest.UserAgent = UserAgent; HttpRequest.CookieContainer = new CookieContainer(); HttpRequest.Referer = this.strRefUrl; HttpRequest.Timeout = this.TimeOut; //优化速度新增 HttpRequest.KeepAlive = false; HttpRequest.ServicePoint.Expect100Continue = false; HttpRequest.ServicePoint.UseNagleAlgorithm = false; HttpRequest.ServicePoint.ConnectionLimit = 65500; HttpRequest.AllowWriteStreamBuffering = false; if ((this._Proxy == null) == false) { HttpRequest.Proxy = this._Proxy; } //HttpRequest.AllowAutoRedirect = False ///''''''''''''''''''''''''''''''''''''''''''''''''''''''' //Accept-Language: zh-cn ///'''''''''''''''''''''''''''''''''''''''''''''''''''''' // 处理Cookie if (((this._cookiePost != null))) { Uri u = new Uri(this._strUrl); foreach (Cookie c in this._cookiePost) { c.Domain = u.Host; } HttpRequest.CookieContainer.Add(this._cookiePost); } ///''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ///处理要发送的数据 if (this._strPostdata.Length > 0) { //如果要发送的数据长度大于0,就以Post方式发送 HttpRequest.ContentType = "application/x-www-form-urlencoded"; if ((this._strPostdata.StartsWith("{") && this._strPostdata.EndsWith("}")) || (this._strPostdata.StartsWith("[") && this._strPostdata.EndsWith("]"))) { HttpRequest.ContentType = "application/json"; } HttpRequest.Method = "POST"; byte[] buf = this._encoding.GetBytes(this._strPostdata); HttpRequest.ContentLength = buf.Length; Stream stream = null; try { stream = HttpRequest.GetRequestStream(); stream.Write(buf, 0, buf.Length); } catch (Exception exception1) { this._strErr = exception1.Message; } finally { if (((stream != null))) { stream.Close(); } } } return HttpRequest; } /// <summary> /// 构造函数 /// </summary> /// <param name="strHttpUrl">发送的地址</param> /// <param name="StrHttpPostData">发送的数据</param> /// <param name="cookiePosted">发送数据的时候使用的cookie</param> /// <remarks>此方法用于以Post方式并附带cookie的发送数据</remarks> public HttpProc(string strHttpUrl, string StrHttpPostData, CookieCollection cookiePosted) { this._strUrl = strHttpUrl; this._strPostdata = StrHttpPostData; this._cookiePost = cookiePosted; } /// <summary> /// 构造函数 /// </summary> /// <param name="strHttpUrl">发送的地址</param> /// <param name="StrHttpPostData">发送的数据</param> /// <remarks>此方法用于以Post方式的发送数据</remarks> public HttpProc(string strHttpUrl, string StrHttpPostData) { this._strUrl = strHttpUrl; this._strPostdata = StrHttpPostData; } /// <summary> /// 构造函数 /// </summary> /// <param name="strHttpUrl">发送的地址</param> /// <param name="cookiePosted">发送数据的时候使用的cookie</param> /// <remarks>此方法用于以GET方式并附带cookie的请求数据</remarks> public HttpProc(string strHttpUrl, CookieCollection cookiePosted) { this._strUrl = strHttpUrl; this._cookiePost = cookiePosted; } /// <summary> /// 构造函数 /// </summary> /// <param name="strHttpUrl">发送的地址</param> /// <remarks>此方法用于以GET方式请求数据</remarks> public HttpProc(string strHttpUrl) : this() { this._strUrl = strHttpUrl; } public HttpProc() { this._encoding = System.Text.Encoding.Default; ServicePointManager.DefaultConnectionLimit = 65500; ServicePointManager.Expect100Continue = false; ServicePointManager.CheckCertificateRevocationList = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; } } //表单基类: public abstract class EntityForm{ //表单名 public EntityForm(string FormName) { Name = FormName; } //编码 private System.Text.Encoding _encoding = System.Text.Encoding.Default; public System.Text.Encoding encoding { get { return _encoding; } set { _encoding = value; } } //边界 private string _boundary = "-----------------------------7d6bb34502ce"; public string boundary { get { return _boundary; } set { _boundary = value; } } //名字 private string _Name; public string Name { get { return _Name; } set { _Name = value; } } public abstract object WriteToStream(System.IO.Stream sw); } //以multipart方式发送文件 public class EntityFormFile : EntityForm{ public EntityFormFile(string FormName, string PostFileName) : base(FormName) { Filename = PostFileName; } //文件名 private string _filename; public string Filename { get { return _filename; } set { _filename = value; } } public override object WriteToStream(System.IO.Stream sw) { if ((sw != null)) { if (System.IO.File.Exists(Filename)) { //先尝试获取ContentType string ext = System.IO.Path.GetExtension(Filename); string ContentType = "application/octet-stream"; if (ext.Length > 0) { Microsoft.Win32.RegistryKey reg = null; try { reg = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext); if ((reg != null)) { ContentType = reg.GetValue("Content Type","").ToString(); } } catch (Exception ex) { ContentType = "application/octet-stream"; } finally { //关闭注册表 if ((reg != null)) { reg.Close(); } } } if (ContentType.Length == 0) { //如果没有获取,就设置到默认 ContentType = "application/octet-stream"; } //写第一行边界 byte[] buf = System.Text.Encoding.ASCII.GetBytes("--" + boundary + Environment.NewLine); sw.Write(buf, 0, buf.Length); //写第二行,类似:Content-Disposition: form-data; name="File1"; filename="D:\frmMain.vb" //写第三行,文件类型 buf = System.Text.Encoding.UTF8.GetBytes(("Content-Disposition: form-data; name=\"" + this.Name + "\"; filename=\"" + this.Filename + "\"" + Environment.NewLine + "Content-Type: " + ContentType + Environment.NewLine + Environment.NewLine)); sw.Write(buf, 0, buf.Length); //开始写文件 System.IO.FileStream sr = null; try { sr = new System.IO.FileStream(Filename, System.IO.FileMode.Open, System.IO.FileAccess.Read); byte[] bufFile = new byte[Math.Min(8192, sr.Length - 1) + 1]; int readed = 0; do { readed = sr.Read(buf, 0, buf.Length); if (readed != 0) { sw.Write(buf, 0, readed); } } while (readed != 0); //追加一个换行 sw.WriteByte(13); sw.WriteByte(10); } catch (Exception ex) { } finally { if ((sr != null)) { sr.Close(); } } } } return ""; } } public class EntityFormValue : EntityForm{ public EntityFormValue(string FormName, string PostFormValue) : base(FormName) { FormValue = PostFormValue; } //表单 private string _Value; public string FormValue { get { return _Value; } set { _Value = value; } } public override object WriteToStream(System.IO.Stream sw) { if ((sw != null)) { string str = ""; byte[] buf = System.Text.Encoding.ASCII.GetBytes("--" + boundary + Environment.NewLine); sw.Write(buf, 0, buf.Length); str += ("Content-Disposition: form-data; name=\"" + this.Name + "\""); str += (Environment.NewLine); //第三行为一个空行 str += (Environment.NewLine); //第四行为表单数值 //str += (System.Web.HttpUtility.UrlEncode(Me.FormValue, encoding)); str += this.FormValue; str += (Environment.NewLine); buf = this.encoding.GetBytes(str); sw.Write(buf, 0, buf.Length); } return ""; } }