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 { /// /// 网络工具类。 /// public sealed class WebUtils { private int _timeout = 20000; private int _readWriteTimeout = 60000; private bool _ignoreSSLCheck = true; private bool _disableWebProxy = false; /// /// 等待请求开始返回的超时时间 /// public int Timeout { get { return this._timeout; } set { this._timeout = value; } } /// /// 等待读取数据完成的超时时间 /// public int ReadWriteTimeout { get { return this._readWriteTimeout; } set { this._readWriteTimeout = value; } } /// /// 是否忽略SSL检查 /// public bool IgnoreSSLCheck { get { return this._ignoreSSLCheck; } set { this._ignoreSSLCheck = value; } } /// /// 是否禁用本地代理 /// public bool DisableWebProxy { get { return this._disableWebProxy; } set { this._disableWebProxy = value; } } /// /// 执行HTTP POST请求。 /// /// 请求地址 /// 请求文本参数 /// HTTP响应 public string DoPost(string url, IDictionary textParams) { return DoPost(url, textParams, null); } /// /// 执行HTTP POST请求。 /// /// 请求地址 /// 请求文本参数 /// 请求头部参数 /// HTTP响应 public string DoPost(string url, IDictionary textParams, IDictionary 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); } /// /// 执行HTTP GET请求。 /// /// 请求地址 /// 请求文本参数 /// HTTP响应 public string DoGet(string url, IDictionary textParams) { return DoGet(url, textParams, null); } /// /// 执行HTTP GET请求。 /// /// 请求地址 /// 请求文本参数 /// 请求头部参数 /// HTTP响应 public string DoGet(string url, IDictionary textParams, IDictionary 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); } /// /// 执行带文件上传的HTTP POST请求。 /// /// 请求地址 /// 请求文本参数 /// 请求文件参数 /// 请求头部参数 /// HTTP响应 public string DoPost(string url, IDictionary textParams, IDictionary fileParams, IDictionary 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 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 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); } /// /// 执行带body体的POST请求。 /// /// 请求地址,含URL参数 /// 请求body体字节流 /// body内容类型 /// 请求头部参数 /// HTTP响应 public string DoPost(string url, byte[] body, string contentType, IDictionary 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); } /// /// 调用请求 /// content type: application/json /// /// The post with json. /// URL. /// Text parameters. /// Header parameters. public string DoPostWithJson(string url, IDictionary textParams, IDictionary 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 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; } /// /// 把响应流转换为文本。 /// /// 响应流对象 /// 编码方式 /// 响应文本 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(); } } /// /// 组装含参数的请求URL。 /// /// 请求地址 /// 请求参数映射 /// 带参数的请求URL public static string BuildRequestUrl(string url, IDictionary parameters) { if (parameters != null && parameters.Count > 0) { return BuildRequestUrl(url, BuildQuery(parameters)); } return url; } /// /// 组装含参数的请求URL。 /// /// 请求地址 /// 一个或多个经过URL编码后的请求参数串 /// 带参数的请求URL 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(); } /// /// 组装普通文本请求参数。 /// /// Key-Value形式请求参数字典 /// URL编码后的请求数据 public static string BuildQuery(IDictionary parameters) { if (parameters == null || parameters.Count == 0) { return null; } StringBuilder query = new StringBuilder(); bool hasParam = false; foreach (KeyValuePair 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证书检查 } } }