| using System; | 
| using System.Collections.Generic; | 
| using System.IO; | 
| using System.IO.Compression; | 
| using System.Net; | 
| using System.Net.Security; | 
| using System.Security.Cryptography.X509Certificates; | 
| using System.Text; | 
| using System.Web; | 
|   | 
| namespace Top.Api.Util | 
| { | 
|     /// <summary> | 
|     /// 网络工具类。 | 
|     /// </summary> | 
|     public sealed class WebUtils | 
|     { | 
|         private int _timeout = 20000; | 
|         private int _readWriteTimeout = 60000; | 
|         private bool _ignoreSSLCheck = true; | 
|         private bool _disableWebProxy = false; | 
|   | 
|         /// <summary> | 
|         /// 等待请求开始返回的超时时间 | 
|         /// </summary> | 
|         public int Timeout | 
|         { | 
|             get { return this._timeout; } | 
|             set { this._timeout = value; } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 等待读取数据完成的超时时间 | 
|         /// </summary> | 
|         public int ReadWriteTimeout | 
|         { | 
|             get { return this._readWriteTimeout; } | 
|             set { this._readWriteTimeout = value; } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 是否忽略SSL检查 | 
|         /// </summary> | 
|         public bool IgnoreSSLCheck | 
|         { | 
|             get { return this._ignoreSSLCheck; } | 
|             set { this._ignoreSSLCheck = value; } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 是否禁用本地代理 | 
|         /// </summary> | 
|         public bool DisableWebProxy | 
|         { | 
|             get { return this._disableWebProxy; } | 
|             set { this._disableWebProxy = value; } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 执行HTTP POST请求。 | 
|         /// </summary> | 
|         /// <param name="url">请求地址</param> | 
|         /// <param name="textParams">请求文本参数</param> | 
|         /// <returns>HTTP响应</returns> | 
|         public string DoPost(string url, IDictionary<string, string> textParams) | 
|         { | 
|             return DoPost(url, textParams, null); | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 执行HTTP POST请求。 | 
|         /// </summary> | 
|         /// <param name="url">请求地址</param> | 
|         /// <param name="textParams">请求文本参数</param> | 
|         /// <param name="headerParams">请求头部参数</param> | 
|         /// <returns>HTTP响应</returns> | 
|         public string DoPost(string url, IDictionary<string, string> textParams, IDictionary<string, string> headerParams) | 
|         { | 
|             HttpWebRequest req = GetWebRequest(url, "POST", headerParams); | 
|             req.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; | 
|   | 
|             byte[] postData = Encoding.UTF8.GetBytes(BuildQuery(textParams)); | 
|             System.IO.Stream reqStream = req.GetRequestStream(); | 
|             reqStream.Write(postData, 0, postData.Length); | 
|             reqStream.Close(); | 
|   | 
|             HttpWebResponse rsp = (HttpWebResponse)req.GetResponse(); | 
|             Encoding encoding = GetResponseEncoding(rsp); | 
|             return GetResponseAsString(rsp, encoding); | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 执行HTTP GET请求。 | 
|         /// </summary> | 
|         /// <param name="url">请求地址</param> | 
|         /// <param name="textParams">请求文本参数</param> | 
|         /// <returns>HTTP响应</returns> | 
|         public string DoGet(string url, IDictionary<string, string> textParams) | 
|         { | 
|             return DoGet(url, textParams, null); | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 执行HTTP GET请求。 | 
|         /// </summary> | 
|         /// <param name="url">请求地址</param> | 
|         /// <param name="textParams">请求文本参数</param> | 
|         /// <param name="headerParams">请求头部参数</param> | 
|         /// <returns>HTTP响应</returns> | 
|         public string DoGet(string url, IDictionary<string, string> textParams, IDictionary<string, string> headerParams) | 
|         { | 
|             if (textParams != null && textParams.Count > 0) | 
|             { | 
|                 url = BuildRequestUrl(url, textParams); | 
|             } | 
|   | 
|             HttpWebRequest req = GetWebRequest(url, "GET", headerParams); | 
|             req.ContentType = "application/x-www-form-urlencoded;charset=gbk"; | 
|   | 
|             HttpWebResponse rsp = (HttpWebResponse)req.GetResponse(); | 
|             Encoding encoding = GetResponseEncoding(rsp); | 
|             return GetResponseAsString(rsp, encoding); | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 执行带文件上传的HTTP POST请求。 | 
|         /// </summary> | 
|         /// <param name="url">请求地址</param> | 
|         /// <param name="textParams">请求文本参数</param> | 
|         /// <param name="fileParams">请求文件参数</param> | 
|         /// <param name="headerParams">请求头部参数</param> | 
|         /// <returns>HTTP响应</returns> | 
|         public string DoPost(string url, IDictionary<string, string> textParams, IDictionary<string, FileItem> fileParams, IDictionary<string, string> headerParams) | 
|         { | 
|             // 如果没有文件参数,则走普通POST请求 | 
|             if (fileParams == null || fileParams.Count == 0) | 
|             { | 
|                 return DoPost(url, textParams, headerParams); | 
|             } | 
|   | 
|             string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线 | 
|   | 
|             HttpWebRequest req = GetWebRequest(url, "POST", headerParams); | 
|             req.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary; | 
|   | 
|             System.IO.Stream reqStream = req.GetRequestStream(); | 
|             byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n"); | 
|             byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); | 
|   | 
|             if(textParams != null) | 
|             { | 
|                 // 组装文本请求参数 | 
|                 string textTemplate = "Content-Disposition:form-data;name=\"{0}\"\r\nContent-Type:text/plain\r\n\r\n{1}"; | 
|                 foreach (KeyValuePair<string, string> kv in textParams) | 
|                 { | 
|                     string textEntry = string.Format(textTemplate, kv.Key, kv.Value); | 
|                     byte[] itemBytes = Encoding.UTF8.GetBytes(textEntry); | 
|                     reqStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length); | 
|                     reqStream.Write(itemBytes, 0, itemBytes.Length); | 
|                 } | 
|             } | 
|   | 
|             // 组装文件请求参数 | 
|             string fileTemplate = "Content-Disposition:form-data;name=\"{0}\";filename=\"{1}\"\r\nContent-Type:{2}\r\n\r\n"; | 
|             foreach (KeyValuePair<string, FileItem> kv in fileParams) | 
|             { | 
|                 string key = kv.Key; | 
|                 FileItem fileItem = kv.Value; | 
|                 if (!fileItem.IsValid()) | 
|                 { | 
|                     throw new ArgumentException("FileItem is invalid"); | 
|                 } | 
|                 string fileEntry = string.Format(fileTemplate, key, fileItem.GetFileName(), fileItem.GetMimeType()); | 
|                 byte[] itemBytes = Encoding.UTF8.GetBytes(fileEntry); | 
|                 reqStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length); | 
|                 reqStream.Write(itemBytes, 0, itemBytes.Length); | 
|                 fileItem.Write(reqStream); | 
|             } | 
|   | 
|             reqStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); | 
|             reqStream.Close(); | 
|   | 
|             HttpWebResponse rsp = (HttpWebResponse)req.GetResponse(); | 
|             Encoding encoding = GetResponseEncoding(rsp); | 
|             return GetResponseAsString(rsp, encoding); | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 执行带body体的POST请求。 | 
|         /// </summary> | 
|         /// <param name="url">请求地址,含URL参数</param> | 
|         /// <param name="body">请求body体字节流</param> | 
|         /// <param name="contentType">body内容类型</param> | 
|         /// <param name="headerParams">请求头部参数</param> | 
|         /// <returns>HTTP响应</returns> | 
|         public string DoPost(string url, byte[] body, string contentType, IDictionary<string, string> headerParams) | 
|         { | 
|             HttpWebRequest req = GetWebRequest(url, "POST", headerParams); | 
|             req.ContentType = contentType; | 
|             if (body != null) | 
|             { | 
|                 System.IO.Stream reqStream = req.GetRequestStream(); | 
|                 reqStream.Write(body, 0, body.Length); | 
|                 reqStream.Close(); | 
|             } | 
|             HttpWebResponse rsp = (HttpWebResponse)req.GetResponse(); | 
|             Encoding encoding = GetResponseEncoding(rsp); | 
|             return GetResponseAsString(rsp, encoding); | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 调用请求 | 
|         /// content type: application/json | 
|         /// </summary> | 
|         /// <returns>The post with json.</returns> | 
|         /// <param name="url">URL.</param> | 
|         /// <param name="textParams">Text parameters.</param> | 
|         /// <param name="headerParams">Header parameters.</param> | 
|         public string DoPostWithJson(string url, IDictionary<string, Object> textParams, IDictionary<string, string> headerParams)  | 
|         { | 
|             HttpWebRequest req = GetWebRequest(url, "POST", headerParams); | 
|             req.ContentType = "application/json;charset=utf-8"; | 
|   | 
|             String body = TopUtils.ObjectToJson(textParams, new FastJSON.JSONParameters() { UseApiNamingStyle = false, UseExtensions = false, SerializeNullValues = false }); | 
|             byte[] postData = Encoding.UTF8.GetBytes(body); | 
|             System.IO.Stream reqStream = req.GetRequestStream(); | 
|             reqStream.Write(postData, 0, postData.Length); | 
|             reqStream.Close(); | 
|   | 
|             HttpWebResponse rsp = (HttpWebResponse)req.GetResponse(); | 
|             Encoding encoding = GetResponseEncoding(rsp); | 
|             return GetResponseAsString(rsp, encoding); | 
|         } | 
|   | 
|         public HttpWebRequest GetWebRequest(string url, string method, IDictionary<string, string> headerParams) | 
|         { | 
|             HttpWebRequest req = null; | 
|             if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) | 
|             { | 
|                 if (this._ignoreSSLCheck) | 
|                 { | 
|                     ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(TrustAllValidationCallback); | 
|                 } | 
|                 req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url)); | 
|             } | 
|             else | 
|             { | 
|                 req = (HttpWebRequest)WebRequest.Create(url); | 
|             } | 
|   | 
|             if (this._disableWebProxy) | 
|             { | 
|                 req.Proxy = null; | 
|             } | 
|   | 
|             if (headerParams != null && headerParams.Count > 0) | 
|             { | 
|                 foreach (string key in headerParams.Keys) | 
|                 { | 
|                     req.Headers.Add(key, headerParams[key]); | 
|                 } | 
|             } | 
|   | 
|             req.ServicePoint.Expect100Continue = false; | 
|             req.Method = method; | 
|             req.KeepAlive = true; | 
|             req.UserAgent = "top-sdk-net"; | 
|             req.Accept = "text/xml,text/javascript"; | 
|             req.Timeout = this._timeout; | 
|             req.ReadWriteTimeout = this._readWriteTimeout; | 
|   | 
|             return req; | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 把响应流转换为文本。 | 
|         /// </summary> | 
|         /// <param name="rsp">响应流对象</param> | 
|         /// <param name="encoding">编码方式</param> | 
|         /// <returns>响应文本</returns> | 
|         public string GetResponseAsString(HttpWebResponse rsp, Encoding encoding) | 
|         { | 
|             Stream stream = null; | 
|             StreamReader reader = null; | 
|   | 
|             try | 
|             { | 
|                 // 以字符流的方式读取HTTP响应 | 
|                 stream = rsp.GetResponseStream(); | 
|                 if (Constants.CONTENT_ENCODING_GZIP.Equals(rsp.ContentEncoding, StringComparison.OrdinalIgnoreCase)) | 
|                 { | 
|                     stream = new GZipStream(stream, CompressionMode.Decompress); | 
|                 } | 
|                 reader = new StreamReader(stream, encoding); | 
|                 return reader.ReadToEnd(); | 
|             } | 
|             finally | 
|             { | 
|                 // 释放资源 | 
|                 if (reader != null) reader.Close(); | 
|                 if (stream != null) stream.Close(); | 
|                 if (rsp != null) rsp.Close(); | 
|             } | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 组装含参数的请求URL。 | 
|         /// </summary> | 
|         /// <param name="url">请求地址</param> | 
|         /// <param name="parameters">请求参数映射</param> | 
|         /// <returns>带参数的请求URL</returns> | 
|         public static string BuildRequestUrl(string url, IDictionary<string, string> parameters) | 
|         { | 
|             if (parameters != null && parameters.Count > 0) | 
|             { | 
|                 return BuildRequestUrl(url, BuildQuery(parameters)); | 
|             } | 
|             return url; | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 组装含参数的请求URL。 | 
|         /// </summary> | 
|         /// <param name="url">请求地址</param> | 
|         /// <param name="queries">一个或多个经过URL编码后的请求参数串</param> | 
|         /// <returns>带参数的请求URL</returns> | 
|         public static string BuildRequestUrl(string url, params string[] queries) | 
|         { | 
|             if (queries == null || queries.Length == 0) | 
|             { | 
|                 return url; | 
|             } | 
|   | 
|             StringBuilder newUrl = new StringBuilder(url); | 
|             bool hasQuery = url.Contains("?"); | 
|             bool hasPrepend = url.EndsWith("?") || url.EndsWith("&"); | 
|   | 
|             foreach (string query in queries) | 
|             { | 
|                 if (!string.IsNullOrEmpty(query)) | 
|                 { | 
|                     if (!hasPrepend) | 
|                     { | 
|                         if (hasQuery) | 
|                         { | 
|                             newUrl.Append("&"); | 
|                         } | 
|                         else | 
|                         { | 
|                             newUrl.Append("?"); | 
|                             hasQuery = true; | 
|                         } | 
|                     } | 
|                     newUrl.Append(query); | 
|                     hasPrepend = false; | 
|                 } | 
|             } | 
|             return newUrl.ToString(); | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 组装普通文本请求参数。 | 
|         /// </summary> | 
|         /// <param name="parameters">Key-Value形式请求参数字典</param> | 
|         /// <returns>URL编码后的请求数据</returns> | 
|         public static string BuildQuery(IDictionary<string, string> parameters) | 
|         { | 
|             if (parameters == null || parameters.Count == 0) | 
|             { | 
|                 return null; | 
|             } | 
|   | 
|             StringBuilder query = new StringBuilder(); | 
|             bool hasParam = false; | 
|   | 
|             foreach (KeyValuePair<string, string> kv in parameters) | 
|             { | 
|                 string name = kv.Key; | 
|                 string value = kv.Value; | 
|                 // 忽略参数名或参数值为空的参数 | 
|                 if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) | 
|                 { | 
|                     if (hasParam) | 
|                     { | 
|                         query.Append("&"); | 
|                     } | 
|   | 
|                     query.Append(name); | 
|                     query.Append("="); | 
|                     query.Append(HttpUtility.UrlEncode(value, Encoding.UTF8)); | 
|                     hasParam = true; | 
|                 } | 
|             } | 
|   | 
|             return query.ToString(); | 
|         } | 
|   | 
|         private Encoding GetResponseEncoding(HttpWebResponse rsp) | 
|         { | 
|             string charset = rsp.CharacterSet; | 
|             if (string.IsNullOrEmpty(charset)) | 
|             { | 
|                 charset = Constants.CHARSET_UTF8; | 
|             } | 
|             return Encoding.GetEncoding(charset); | 
|         } | 
|   | 
|         private static bool TrustAllValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) | 
|         { | 
|             return true; // 忽略SSL证书检查 | 
|         } | 
|     } | 
| } |