常用类-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; } } }