HttpProc.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. using System;
  2. using System.Text;
  3. using System.IO;
  4. using System.Net;
  5. using System.Net.Security;
  6. using System.Security.Cryptography.X509Certificates;
  7. using System.IO.Compression;
  8. using System.Net.Cache;
  9. namespace Ant.Service.Utilities
  10. {
  11. /// <summary>
  12. /// 上传数据参数
  13. /// </summary>
  14. public class UploadEventArgs : EventArgs
  15. {
  16. int bytesSent;
  17. int totalBytes;
  18. /// <summary>
  19. /// 已发送的字节数
  20. /// </summary>
  21. public int BytesSent
  22. {
  23. get { return bytesSent; }
  24. set { bytesSent = value; }
  25. }
  26. /// <summary>
  27. /// 总字节数
  28. /// </summary>
  29. public int TotalBytes
  30. {
  31. get { return totalBytes; }
  32. set { totalBytes = value; }
  33. }
  34. }
  35. /// <summary>
  36. /// 下载数据参数
  37. /// </summary>
  38. public class DownloadEventArgs : EventArgs
  39. {
  40. int bytesReceived;
  41. int totalBytes;
  42. byte[] receivedData;
  43. /// <summary>
  44. /// 已接收的字节数
  45. /// </summary>
  46. public int BytesReceived
  47. {
  48. get { return bytesReceived; }
  49. set { bytesReceived = value; }
  50. }
  51. /// <summary>
  52. /// 总字节数
  53. /// </summary>
  54. public int TotalBytes
  55. {
  56. get { return totalBytes; }
  57. set { totalBytes = value; }
  58. }
  59. /// <summary>
  60. /// 当前缓冲区接收的数据
  61. /// </summary>
  62. public byte[] ReceivedData
  63. {
  64. get { return receivedData; }
  65. set { receivedData = value; }
  66. }
  67. }
  68. public class WebClients
  69. {
  70. Encoding encoding = Encoding.Default;
  71. string respHtml = "";
  72. WebProxy proxy;
  73. static CookieContainer cc;
  74. WebHeaderCollection requestHeaders;
  75. WebHeaderCollection responseHeaders;
  76. int bufferSize = 15240;
  77. public event EventHandler<UploadEventArgs> UploadProgressChanged;
  78. public event EventHandler<DownloadEventArgs> DownloadProgressChanged;
  79. static WebClients()
  80. {
  81. LoadCookiesFromDisk();
  82. }
  83. /// <summary>
  84. /// 创建WebClient的实例
  85. /// </summary>
  86. public WebClients()
  87. {
  88. requestHeaders = new WebHeaderCollection();
  89. responseHeaders = new WebHeaderCollection();
  90. }
  91. /// <summary>
  92. /// 设置发送和接收的数据缓冲大小
  93. /// </summary>
  94. public int BufferSize
  95. {
  96. get { return bufferSize; }
  97. set { bufferSize = value; }
  98. }
  99. /// <summary>
  100. /// 获取响应头集合
  101. /// </summary>
  102. public WebHeaderCollection ResponseHeaders
  103. {
  104. get { return responseHeaders; }
  105. }
  106. /// <summary>
  107. /// 获取请求头集合
  108. /// </summary>
  109. public WebHeaderCollection RequestHeaders
  110. {
  111. get { return requestHeaders; }
  112. }
  113. /// <summary>
  114. /// 获取或设置代理
  115. /// </summary>
  116. public WebProxy Proxy
  117. {
  118. get { return proxy; }
  119. set { proxy = value; }
  120. }
  121. /// <summary>
  122. /// 获取或设置请求与响应的文本编码方式
  123. /// </summary>
  124. public Encoding Encoding
  125. {
  126. get { return encoding; }
  127. set { encoding = value; }
  128. }
  129. /// <summary>
  130. /// 获取或设置响应的html代码
  131. /// </summary>
  132. public string RespHtml
  133. {
  134. get { return respHtml; }
  135. set { respHtml = value; }
  136. }
  137. /// <summary>
  138. /// 获取或设置与请求关联的Cookie容器
  139. /// </summary>
  140. public CookieContainer CookieContainer
  141. {
  142. get { return cc; }
  143. set { cc = value; }
  144. }
  145. /// <summary>
  146. /// 获取网页源代码
  147. /// </summary>
  148. /// <param name="url">网址</param>
  149. /// <returns></returns>
  150. public string GetHtml(string url)
  151. {
  152. HttpWebRequest request = CreateRequest(url, "GET");
  153. respHtml = encoding.GetString(GetData(request));
  154. return respHtml;
  155. }
  156. /// <summary>
  157. /// 下载文件
  158. /// </summary>
  159. /// <param name="url">文件URL地址</param>
  160. /// <param name="filename">文件保存完整路径</param>
  161. public void DownloadFile(string url, string filename)
  162. {
  163. FileStream fs = null;
  164. try
  165. {
  166. HttpWebRequest request = CreateRequest(url, "GET");
  167. byte[] data = GetData(request);
  168. fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
  169. fs.Write(data, 0, data.Length);
  170. }
  171. finally
  172. {
  173. if (fs != null) fs.Close();
  174. }
  175. }
  176. /// <summary>
  177. /// 从指定URL下载数据
  178. /// </summary>
  179. /// <param name="url">网址</param>
  180. /// <returns></returns>
  181. public byte[] GetData(string url)
  182. {
  183. HttpWebRequest request = CreateRequest(url, "GET");
  184. return GetData(request);
  185. }
  186. /// <summary>
  187. /// 向指定URL发送文本数据
  188. /// </summary>
  189. /// <param name="url">网址</param>
  190. /// <param name="postData">urlencode编码的文本数据</param>
  191. /// <returns></returns>
  192. public string Post(string url, string postData)
  193. {
  194. byte[] data = encoding.GetBytes(postData);
  195. return Post(url, data);
  196. }
  197. /// <summary>
  198. /// 向指定URL发送字节数据
  199. /// </summary>
  200. /// <param name="url">网址</param>
  201. /// <param name="postData">发送的字节数组</param>
  202. /// <returns></returns>
  203. public string Post(string url, byte[] postData)
  204. {
  205. HttpWebRequest request = CreateRequest(url, "POST");
  206. request.ContentType = "application/x-www-form-urlencoded";
  207. request.ContentLength = postData.Length;
  208. request.KeepAlive = true;
  209. PostData(request, postData);
  210. respHtml = encoding.GetString(GetData(request));
  211. return respHtml;
  212. }
  213. /// <summary>
  214. /// 向指定网址发送mulitpart编码的数据
  215. /// </summary>
  216. /// <param name="url">网址</param>
  217. /// <param name="mulitpartForm">mulitpart form data</param>
  218. /// <returns></returns>
  219. public string Post(string url, MultipartForm mulitpartForm)
  220. {
  221. HttpWebRequest request = CreateRequest(url, "POST");
  222. request.ContentType = mulitpartForm.ContentType;
  223. request.ContentLength = mulitpartForm.FormData.Length;
  224. request.KeepAlive = true;
  225. PostData(request, mulitpartForm.FormData);
  226. respHtml = encoding.GetString(GetData(request));
  227. return respHtml;
  228. }
  229. /// <summary>
  230. /// 读取请求返回的数据
  231. /// </summary>
  232. /// <param name="request">请求对象</param>
  233. /// <returns></returns>
  234. private byte[] GetData(HttpWebRequest request)
  235. {
  236. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  237. Stream stream = response.GetResponseStream();
  238. responseHeaders = response.Headers;
  239. //SaveCookiesToDisk();
  240. DownloadEventArgs args = new DownloadEventArgs();
  241. if (responseHeaders[HttpResponseHeader.ContentLength] != null)
  242. args.TotalBytes = Convert.ToInt32(responseHeaders[HttpResponseHeader.ContentLength]);
  243. MemoryStream ms = new MemoryStream();
  244. int count = 0;
  245. byte[] buf = new byte[bufferSize];
  246. while ((count = stream.Read(buf, 0, buf.Length)) > 0)
  247. {
  248. ms.Write(buf, 0, count);
  249. if (this.DownloadProgressChanged != null)
  250. {
  251. args.BytesReceived += count;
  252. args.ReceivedData = new byte[count];
  253. Array.Copy(buf, args.ReceivedData, count);
  254. this.DownloadProgressChanged(this, args);
  255. }
  256. }
  257. stream.Close();
  258. //解压
  259. if (ResponseHeaders[HttpResponseHeader.ContentEncoding] != null)
  260. {
  261. MemoryStream msTemp = new MemoryStream();
  262. count = 0;
  263. buf = new byte[100];
  264. switch (ResponseHeaders[HttpResponseHeader.ContentEncoding].ToLower())
  265. {
  266. case "gzip":
  267. GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress);
  268. while ((count = gzip.Read(buf, 0, buf.Length)) > 0)
  269. {
  270. msTemp.Write(buf, 0, count);
  271. }
  272. return msTemp.ToArray();
  273. case "deflate":
  274. DeflateStream deflate = new DeflateStream(ms, CompressionMode.Decompress);
  275. while ((count = deflate.Read(buf, 0, buf.Length)) > 0)
  276. {
  277. msTemp.Write(buf, 0, count);
  278. }
  279. return msTemp.ToArray();
  280. default:
  281. break;
  282. }
  283. }
  284. return ms.ToArray();
  285. }
  286. /// <summary>
  287. /// 发送请求数据
  288. /// </summary>
  289. /// <param name="request">请求对象</param>
  290. /// <param name="postData">请求发送的字节数组</param>
  291. private void PostData(HttpWebRequest request, byte[] postData)
  292. {
  293. int offset = 0;
  294. int sendBufferSize = bufferSize;
  295. int remainBytes = 0;
  296. Stream stream = request.GetRequestStream();
  297. UploadEventArgs args = new UploadEventArgs();
  298. args.TotalBytes = postData.Length;
  299. while ((remainBytes = postData.Length - offset) > 0)
  300. {
  301. if (sendBufferSize > remainBytes) sendBufferSize = remainBytes;
  302. stream.Write(postData, offset, sendBufferSize);
  303. offset += sendBufferSize;
  304. if (this.UploadProgressChanged != null)
  305. {
  306. args.BytesSent = offset;
  307. this.UploadProgressChanged(this, args);
  308. }
  309. }
  310. stream.Close();
  311. }
  312. /// <summary>
  313. /// 创建HTTP请求
  314. /// </summary>
  315. /// <param name="url">URL地址</param>
  316. /// <returns></returns>
  317. private HttpWebRequest CreateRequest(string url, string method)
  318. {
  319. Uri uri = new Uri(url);
  320. if (uri.Scheme == "https")
  321. ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(this.CheckValidationResult);
  322. // Set a default policy level for the "http:" and "https" schemes.
  323. HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Revalidate);
  324. HttpWebRequest.DefaultCachePolicy = policy;
  325. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
  326. request.AllowAutoRedirect = false;
  327. request.AllowWriteStreamBuffering = false;
  328. request.Method = method;
  329. if (proxy != null)
  330. request.Proxy = proxy;
  331. request.CookieContainer = cc;
  332. foreach (string key in requestHeaders.Keys)
  333. {
  334. request.Headers.Add(key, requestHeaders[key]);
  335. }
  336. requestHeaders.Clear();
  337. return request;
  338. }
  339. private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
  340. {
  341. return true;
  342. }
  343. /// <summary>
  344. /// 将Cookie保存到磁盘
  345. /// </summary>
  346. private static void SaveCookiesToDisk()
  347. {
  348. string cookieFile = System.Environment.GetFolderPath(Environment.SpecialFolder.Cookies) + "\\webclient.cookie";
  349. FileStream fs = null;
  350. try
  351. {
  352. fs = new FileStream(cookieFile, FileMode.Create);
  353. System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formater = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
  354. formater.Serialize(fs, cc);
  355. }
  356. finally
  357. {
  358. if (fs != null) fs.Close();
  359. }
  360. }
  361. /// <summary>
  362. /// 从磁盘加载Cookie
  363. /// </summary>
  364. private static void LoadCookiesFromDisk()
  365. {
  366. cc = new CookieContainer();
  367. string cookieFile = System.Environment.GetFolderPath(Environment.SpecialFolder.Cookies) + "\\webclient.cookie";
  368. if (!File.Exists(cookieFile))
  369. return;
  370. FileStream fs = null;
  371. try
  372. {
  373. fs = new FileStream(cookieFile, FileMode.Open, FileAccess.Read, FileShare.Read);
  374. System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formater = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
  375. cc = (CookieContainer)formater.Deserialize(fs);
  376. }
  377. finally
  378. {
  379. if (fs != null) fs.Close();
  380. }
  381. }
  382. }
  383. /// <summary>
  384. /// 对文件和文本数据进行Multipart形式的编码
  385. /// </summary>
  386. public class MultipartForm
  387. {
  388. private Encoding encoding;
  389. private MemoryStream ms;
  390. private string boundary;
  391. private byte[] formData;
  392. /// <summary>
  393. /// 获取编码后的字节数组
  394. /// </summary>
  395. public byte[] FormData
  396. {
  397. get
  398. {
  399. if (formData == null)
  400. {
  401. byte[] buffer = encoding.GetBytes("--" + this.boundary + "--\r\n");
  402. ms.Write(buffer, 0, buffer.Length);
  403. formData = ms.ToArray();
  404. }
  405. return formData;
  406. }
  407. }
  408. /// <summary>
  409. /// 获取此编码内容的类型
  410. /// </summary>
  411. public string ContentType
  412. {
  413. get { return string.Format("multipart/form-data; boundary={0}", this.boundary); }
  414. }
  415. /// <summary>
  416. /// 获取或设置对字符串采用的编码类型
  417. /// </summary>
  418. public Encoding StringEncoding
  419. {
  420. set { encoding = value; }
  421. get { return encoding; }
  422. }
  423. /// <summary>
  424. /// 实例化
  425. /// </summary>
  426. public MultipartForm()
  427. {
  428. boundary = string.Format("--{0}--", Guid.NewGuid());
  429. ms = new MemoryStream();
  430. encoding = Encoding.Default;
  431. }
  432. /// <summary>
  433. /// 添加一个文件
  434. /// </summary>
  435. /// <param name="name">文件域名称</param>
  436. /// <param name="filename">文件的完整路径</param>
  437. public void AddFlie(string name, string filename)
  438. {
  439. if (!File.Exists(filename))
  440. throw new FileNotFoundException("尝试添加不存在的文件。", filename);
  441. FileStream fs = null;
  442. byte[] fileData = { };
  443. try
  444. {
  445. fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
  446. fileData = new byte[fs.Length];
  447. fs.Read(fileData, 0, fileData.Length);
  448. this.AddFlie(name, Path.GetFileName(filename), fileData, fileData.Length);
  449. }
  450. catch (Exception)
  451. {
  452. throw;
  453. }
  454. finally
  455. {
  456. if (fs != null) fs.Close();
  457. }
  458. }
  459. /// <summary>
  460. /// 添加一个文件
  461. /// </summary>
  462. /// <param name="name">文件域名称</param>
  463. /// <param name="filename">文件名</param>
  464. /// <param name="fileData">文件二进制数据</param>
  465. /// <param name="dataLength">二进制数据大小</param>
  466. public void AddFlie(string name, string filename, byte[] fileData, int dataLength)
  467. {
  468. if (dataLength <= 0 || dataLength > fileData.Length)
  469. {
  470. dataLength = fileData.Length;
  471. }
  472. StringBuilder sb = new StringBuilder();
  473. sb.AppendFormat("--{0}\r\n", this.boundary);
  474. sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\n", name, filename);
  475. sb.AppendFormat("Content-Type: {0}\r\n", this.GetContentType(filename));
  476. sb.Append("\r\n");
  477. byte[] buf = encoding.GetBytes(sb.ToString());
  478. ms.Write(buf, 0, buf.Length);
  479. ms.Write(fileData, 0, dataLength);
  480. byte[] crlf = encoding.GetBytes("\r\n");
  481. ms.Write(crlf, 0, crlf.Length);
  482. }
  483. /// <summary>
  484. /// 添加字符串
  485. /// </summary>
  486. /// <param name="name">文本域名称</param>
  487. /// <param name="value">文本值</param>
  488. public void AddString(string name, string value)
  489. {
  490. StringBuilder sb = new StringBuilder();
  491. sb.AppendFormat("--{0}\r\n", this.boundary);
  492. sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\"\r\n", name);
  493. sb.Append("\r\n");
  494. sb.AppendFormat("{0}\r\n", value);
  495. byte[] buf = encoding.GetBytes(sb.ToString());
  496. ms.Write(buf, 0, buf.Length);
  497. }
  498. /// <summary>
  499. /// 从注册表获取文件类型
  500. /// </summary>
  501. /// <param name="filename">包含扩展名的文件名</param>
  502. /// <returns>如:application/stream</returns>
  503. private string GetContentType(string filename)
  504. {
  505. Microsoft.Win32.RegistryKey fileExtKey = null; ;
  506. string contentType = "application/stream";
  507. try
  508. {
  509. fileExtKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(Path.GetExtension(filename));
  510. contentType = fileExtKey.GetValue("Content Type", contentType).ToString();
  511. }
  512. finally
  513. {
  514. if (fileExtKey != null) fileExtKey.Close();
  515. }
  516. return contentType;
  517. }
  518. }
  519. }