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证书检查
}
}
}