WebUtils.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. using System;
  2. using System.Threading.Tasks;
  3. using System.Web;
  4. using System.IO;
  5. using System.Net;
  6. using System.Text;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. namespace Aop.Api.Util
  10. {
  11. /// <summary>
  12. /// 网络工具类。
  13. /// </summary>
  14. public sealed class WebUtils
  15. {
  16. private int _timeout = 100000;
  17. /// <summary>
  18. /// 请求与响应的超时时间
  19. /// </summary>
  20. public int Timeout
  21. {
  22. get { return this._timeout; }
  23. set { this._timeout = value; }
  24. }
  25. /// <summary>
  26. /// 执行HTTP POST请求。
  27. /// </summary>
  28. /// <param name="url">请求地址</param>
  29. /// <param name="parameters">请求参数</param>
  30. /// <param name="charset">编码字符集</param>
  31. /// <returns>HTTP响应</returns>
  32. public async Task<string> DoPost(string url, IDictionary<string, string> parameters, string charset)
  33. {
  34. try
  35. {
  36. HttpWebRequest req = GetWebRequest(url, "POST");
  37. req.ContentType = "application/x-www-form-urlencoded;charset=" + charset;
  38. byte[] postData = Encoding.GetEncoding(charset).GetBytes(BuildQuery(parameters, charset));
  39. Stream reqStream = await req.GetRequestStreamAsync();
  40. reqStream.Write(postData, 0, postData.Length);
  41. reqStream.Close();
  42. var r = await req.GetResponseAsync();
  43. var rsp = (HttpWebResponse)r;
  44. Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet);
  45. return GetResponseAsString(rsp, encoding);
  46. }
  47. catch (Exception ex)
  48. {
  49. return null;
  50. }
  51. }
  52. /// <summary>
  53. /// 执行HTTP GET请求。
  54. /// </summary>
  55. /// <param name="url">请求地址</param>
  56. /// <param name="parameters">请求参数</param>
  57. /// <param name="charset">编码字符集</param>
  58. /// <returns>HTTP响应</returns>
  59. public string DoGet(string url, IDictionary<string, string> parameters, string charset)
  60. {
  61. if (parameters != null && parameters.Count > 0)
  62. {
  63. if (url.Contains("?"))
  64. {
  65. url = url + "&" + BuildQuery(parameters, charset);
  66. }
  67. else
  68. {
  69. url = url + "?" + BuildQuery(parameters, charset);
  70. }
  71. }
  72. HttpWebRequest req = GetWebRequest(url, "GET");
  73. req.ContentType = "application/x-www-form-urlencoded;charset=" + charset;
  74. HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
  75. Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet);
  76. return GetResponseAsString(rsp, encoding);
  77. }
  78. /// <summary>
  79. /// 执行带文件上传的HTTP POST请求。
  80. /// </summary>
  81. /// <param name="url">请求地址</param>
  82. /// <param name="textParams">请求文本参数</param>
  83. /// <param name="fileParams">请求文件参数</param>
  84. /// <param name="charset">编码字符集</param>
  85. /// <returns>HTTP响应</returns>
  86. public async Task<string> DoPost(string url, IDictionary<string, string> textParams, IDictionary<string, FileItem> fileParams, string charset)
  87. {
  88. // 如果没有文件参数,则走普通POST请求
  89. if (fileParams == null || fileParams.Count == 0)
  90. {
  91. return await DoPost(url, textParams, charset);
  92. }
  93. string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线
  94. HttpWebRequest req = GetWebRequest(url, "POST");
  95. req.ContentType = "multipart/form-data;charset=" + charset + ";boundary=" + boundary;
  96. Stream reqStream = await req.GetRequestStreamAsync();
  97. byte[] itemBoundaryBytes = Encoding.GetEncoding(charset).GetBytes("\r\n--" + boundary + "\r\n");
  98. byte[] endBoundaryBytes = Encoding.GetEncoding(charset).GetBytes("\r\n--" + boundary + "--\r\n");
  99. // 组装文本请求参数
  100. string textTemplate = "Content-Disposition:form-data;name=\"{0}\"\r\nContent-Type:text/plain\r\n\r\n{1}";
  101. IEnumerator<KeyValuePair<string, string>> textEnum = textParams.GetEnumerator();
  102. while (textEnum.MoveNext())
  103. {
  104. string textEntry = string.Format(textTemplate, textEnum.Current.Key, textEnum.Current.Value);
  105. byte[] itemBytes = Encoding.GetEncoding(charset).GetBytes(textEntry);
  106. reqStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
  107. reqStream.Write(itemBytes, 0, itemBytes.Length);
  108. }
  109. // 组装文件请求参数
  110. string fileTemplate = "Content-Disposition:form-data;name=\"{0}\";filename=\"{1}\"\r\nContent-Type:{2}\r\n\r\n";
  111. IEnumerator<KeyValuePair<string, FileItem>> fileEnum = fileParams.GetEnumerator();
  112. while (fileEnum.MoveNext())
  113. {
  114. string key = fileEnum.Current.Key;
  115. FileItem fileItem = fileEnum.Current.Value;
  116. string fileEntry = string.Format(fileTemplate, key, fileItem.GetFileName(), fileItem.GetMimeType());
  117. byte[] itemBytes = Encoding.GetEncoding(charset).GetBytes(fileEntry);
  118. reqStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
  119. reqStream.Write(itemBytes, 0, itemBytes.Length);
  120. byte[] fileBytes = fileItem.GetContent();
  121. reqStream.Write(fileBytes, 0, fileBytes.Length);
  122. }
  123. reqStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
  124. reqStream.Close();
  125. HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
  126. Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet);
  127. return GetResponseAsString(rsp, encoding);
  128. }
  129. public HttpWebRequest GetWebRequest(string url, string method)
  130. {
  131. HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
  132. req.ServicePoint.Expect100Continue = false;
  133. req.Method = method;
  134. req.KeepAlive = true;
  135. req.UserAgent = "Aop4Net";
  136. req.Timeout = this._timeout;
  137. return req;
  138. }
  139. /// <summary>
  140. /// 把响应流转换为文本。
  141. /// </summary>
  142. /// <param name="rsp">响应流对象</param>
  143. /// <param name="encoding">编码方式</param>
  144. /// <returns>响应文本</returns>
  145. public string GetResponseAsString(HttpWebResponse rsp, Encoding encoding)
  146. {
  147. StringBuilder result = new StringBuilder();
  148. Stream stream = null;
  149. StreamReader reader = null;
  150. try
  151. {
  152. // 以字符流的方式读取HTTP响应
  153. stream = rsp.GetResponseStream();
  154. reader = new StreamReader(stream, encoding);
  155. // 按字符读取并写入字符串缓冲
  156. int ch = -1;
  157. while ((ch = reader.Read()) > -1)
  158. {
  159. // 过滤结束符
  160. char c = (char)ch;
  161. if (c != '\0')
  162. {
  163. result.Append(c);
  164. }
  165. }
  166. }
  167. finally
  168. {
  169. // 释放资源
  170. if (reader != null) reader.Close();
  171. if (stream != null) stream.Close();
  172. if (rsp != null) rsp.Close();
  173. }
  174. return result.ToString();
  175. }
  176. /// <summary>
  177. /// 组装普通文本请求参数。
  178. /// </summary>
  179. /// <param name="parameters">Key-Value形式请求参数字典</param>
  180. /// <returns>URL编码后的请求数据</returns>
  181. public static string BuildQuery(IDictionary<string, string> parameters, string charset)
  182. {
  183. StringBuilder postData = new StringBuilder();
  184. bool hasParam = false;
  185. IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
  186. while (dem.MoveNext())
  187. {
  188. string name = dem.Current.Key;
  189. string value = dem.Current.Value;
  190. // 忽略参数名或参数值为空的参数
  191. if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value))
  192. {
  193. if (hasParam)
  194. {
  195. postData.Append("&");
  196. }
  197. postData.Append(name);
  198. postData.Append("=");
  199. string encodedValue = HttpUtility.UrlEncode(value, Encoding.GetEncoding(charset));
  200. postData.Append(encodedValue);
  201. hasParam = true;
  202. }
  203. }
  204. return postData.ToString();
  205. }
  206. }
  207. }