惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
The Last Watchdog
The Last Watchdog
Cyberwarzone
Cyberwarzone
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Cloudflare Blog
V
V2EX
博客园_首页
博客园 - 聂微东
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
T
Tenable Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
SecWiki News
SecWiki News
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
D
DataBreaches.Net
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
D
Docker
P
Proofpoint News Feed

博客园 - 浪端之渡鸟

老鼠跑猫叫主人惊醒c++观察者模式实现 讨论exe获取dll提供的单例,并获取单例所提供的带有vector<class A>& STL容器的返回值的情况-提供1种解决方法 vs2010 mfc dll 调试编译的问题 std::stringstream 模版实现,类型转换,遇到空格不跳出 字节对齐,对opencv的影响 跨平台,c语言创建多级路径代码分享 吐槽VS2010,卡死后,一直不能点,强制关机后代码丢失 IOS App资源路径 opencv在MFC下使用的问题 fopen的打开方式 解决安装macports,不能更新的问题 坑爹啊,新手一个这问题折腾2天,xcode4.5拖上去控件真机调试就崩 静态页面转化 删除_svn文件夹 开发相关日志 symbian 输入控件不显示输入法解决: V3 V5宏定义 coco2d-x 重置z轴 htmlcontrol-for-symbian 源码解析
WebClient.cs封装
浪端之渡鸟 · 2012-04-02 · via 博客园 - 浪端之渡鸟

Posted on 2012-04-02 07:53  浪端之渡鸟  阅读(1981)  评论()    收藏  举报

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Collections;
  7. using System.IO;
  8. using System.Text.RegularExpressions;
  9. using RE = System.Text.RegularExpressions.Regex;
  10. using System.Security.Cryptography.X509Certificates;
  11. /***************************************************************************************************************************************************
  12. * *文件名:HttpProc.cs
  13. * *创建人:kenter
  14. * *日 期:2010.02.23 修改
  15. * *描 述:实现HTTP协议中的GET、POST请求
  16. * *使 用:HttpProc.WebClient client = new HttpProc.WebClient();
  17. client.Encoding = System.Text.Encoding.Default;//默认编码方式,根据需要设置其他类型
  18. client.OpenRead("http://www.baidu.com");//普通get请求
  19. MessageBox.Show(client.RespHtml);//获取返回的网页源代码
  20. client.DownloadFile("http://www.codepub.com/upload/163album.rar",@"C:\163album.rar");//下载文件
  21. client.OpenRead("http://passport.baidu.com/?login","username=zhangsan&password=123456");//提交表单,此处是登录百度的示例
  22. client.UploadFile("http://hiup.baidu.com/zhangsan/upload", @"file1=D:\1.mp3");//上传文件
  23. client.UploadFile("http://hiup.baidu.com/zhangsan/upload", "folder=myfolder&size=4003550",@"file1=D:\1.mp3");//提交含文本域和文件域的表单
  24. *****************************************************************************************************************************************************/
  25. namespace HttpProc
  26. {
  27. ///<summary>
  28. ///上传事件委托
  29. ///</summary>
  30. ///<param name="sender"></param>
  31. ///<param name="e"></param>
  32. public delegate void WebClientUploadEvent(object sender, HttpProc.UploadEventArgs e);
  33. ///<summary>
  34. ///下载事件委托
  35. ///</summary>
  36. ///<param name="sender"></param>
  37. ///<param name="e"></param>
  38. public delegate void WebClientDownloadEvent(object sender, HttpProc.DownloadEventArgs e);
  39. ///<summary>
  40. ///上传事件参数
  41. ///</summary>
  42. public struct UploadEventArgs
  43. {
  44. ///<summary>
  45. ///上传数据总大小
  46. ///</summary>
  47. public long totalBytes;
  48. ///<summary>
  49. ///已发数据大小
  50. ///</summary>
  51. public long bytesSent;
  52. ///<summary>
  53. ///发送进度(0-1)
  54. ///</summary>
  55. public double sendProgress;
  56. ///<summary>
  57. ///发送速度Bytes/s
  58. ///</summary>
  59. public double sendSpeed;
  60. }
  61. ///<summary>
  62. ///下载事件参数
  63. ///</summary>
  64. public struct DownloadEventArgs
  65. {
  66. ///<summary>
  67. ///下载数据总大小
  68. ///</summary>
  69. public long totalBytes;
  70. ///<summary>
  71. ///已接收数据大小
  72. ///</summary>
  73. public long bytesReceived;
  74. ///<summary>
  75. ///接收数据进度(0-1)
  76. ///</summary>
  77. public double ReceiveProgress;
  78. ///<summary>
  79. ///当前缓冲区数据
  80. ///</summary>
  81. public byte[] receivedBuffer;
  82. ///<summary>
  83. ///接收速度Bytes/s
  84. ///</summary>
  85. public double receiveSpeed;
  86. }
  87. ///<summary>
  88. ///实现向WEB服务器发送和接收数据
  89. ///</summary>
  90. public class WebClient
  91. {
  92. private WebHeaderCollection requestHeaders, responseHeaders;
  93. private TcpClient clientSocket;
  94. private MemoryStream postStream;
  95. private Encoding encoding = Encoding.Default;
  96. private const string BOUNDARY = "--HEDAODE--";
  97. private const int SEND_BUFFER_SIZE = 10245;
  98. private const int RECEIVE_BUFFER_SIZE = 10245;
  99. private string cookie = "";
  100. private string respHtml = "";
  101. private string strRequestHeaders = "";
  102. private string strResponseHeaders = "";
  103. private int statusCode = 0;
  104. private bool isCanceled = false;
  105. public event WebClientUploadEvent UploadProgressChanged;
  106. public event WebClientDownloadEvent DownloadProgressChanged;
  107. ///<summary>
  108. ///初始化WebClient类
  109. ///</summary>
  110. public WebClient()
  111. {
  112. responseHeaders = new WebHeaderCollection();
  113. requestHeaders = new WebHeaderCollection();
  114. }
  115. /// <summary>
  116. /// 获得字符串中开始和结束字符串中间得值
  117. /// </summary>
  118. /// <param name="str"></param>
  119. /// <param name="s">开始</param>
  120. /// <param name="e">结束</param>
  121. /// <returns></returns>
  122. public string gethtmlContent(string str, string s, string e)
  123. {
  124. Regex rg = new Regex("(?<=(" + s + "))[.\\s\\S]*?(?=(" + e + "))", RegexOptions.Multiline | RegexOptions.Singleline);
  125. return rg.Match(str).Value;
  126. }
  127. /// <summary>
  128. /// 过滤HTML字符
  129. /// </summary>
  130. /// <param name="source"></param>
  131. /// <returns></returns>
  132. public string htmlConvert(string source)
  133. {
  134. string result;
  135. //remove line breaks,tabs
  136. result = source.Replace("\r", " ");
  137. result = result.Replace("\n", " ");
  138. result = result.Replace("\t", " ");
  139. //remove the header
  140. result = Regex.Replace(result, "(<head>).*(</head>)", string.Empty, RegexOptions.IgnoreCase);
  141. result = Regex.Replace(result, @"<( )*script([^>])*>", "<script>", RegexOptions.IgnoreCase);
  142. result = Regex.Replace(result, @"(<script>).*(</script>)", string.Empty, RegexOptions.IgnoreCase);
  143. //remove all styles
  144. result = Regex.Replace(result, @"<( )*style([^>])*>", "<style>", RegexOptions.IgnoreCase); //clearing attributes
  145. result = Regex.Replace(result, "(<style>).*(</style>)", string.Empty, RegexOptions.IgnoreCase);
  146. //insert tabs in spaces of <td> tags
  147. result = Regex.Replace(result, @"<( )*td([^>])*>", " ", RegexOptions.IgnoreCase);
  148. //insert line breaks in places of <br> and <li> tags
  149. result = Regex.Replace(result, @"<( )*br( )*>", "\r", RegexOptions.IgnoreCase);
  150. result = Regex.Replace(result, @"<( )*li( )*>", "\r", RegexOptions.IgnoreCase);
  151. //insert line paragraphs in places of <tr> and <p> tags
  152. result = Regex.Replace(result, @"<( )*tr([^>])*>", "\r\r", RegexOptions.IgnoreCase);
  153. result = Regex.Replace(result, @"<( )*p([^>])*>", "\r\r", RegexOptions.IgnoreCase);
  154. //remove anything thats enclosed inside < >
  155. result = Regex.Replace(result, @"<[^>]*>", string.Empty, RegexOptions.IgnoreCase);
  156. //replace special characters:
  157. result = Regex.Replace(result, @"&amp;", "&", RegexOptions.IgnoreCase);
  158. result = Regex.Replace(result, @"&nbsp;", " ", RegexOptions.IgnoreCase);
  159. result = Regex.Replace(result, @"&lt;", "<", RegexOptions.IgnoreCase);
  160. result = Regex.Replace(result, @"&gt;", ">", RegexOptions.IgnoreCase);
  161. result = Regex.Replace(result, @"&(.{2,6});", string.Empty, RegexOptions.IgnoreCase);
  162. //remove extra line breaks and tabs
  163. result = Regex.Replace(result, @" ( )+", " ");
  164. result = Regex.Replace(result, "(\r)( )+(\r)", "\r\r");
  165. result = Regex.Replace(result, @"(\r\r)+", "\r\n");
  166. return result;
  167. }
  168. ///<summary>
  169. ///读取指定URL的文本
  170. ///</summary>
  171. ///<param name="URL">请求的地址</param>
  172. ///<returns>服务器响应文本</returns>
  173. public string OpenRead(string URL)
  174. {
  175. requestHeaders.Add("Connection", "close");
  176. SendRequestData(URL, "GET");
  177. return GetHtml();
  178. }
  179. //解决证书过期无法访问的问题
  180. class CertPolicy : ICertificatePolicy
  181. {
  182. public bool CheckValidationResult(ServicePoint srvpt, X509Certificate cert, WebRequest req, int certprb)
  183. { return true; }
  184. }
  185. ///<summary>
  186. ///采用https协议访问网络
  187. ///</summary>
  188. ///<param name="URL">url地址</param>
  189. ///<param name="strPostdata">发送的数据</param>
  190. ///<returns></returns>
  191. public string OpenReadWithHttps(string URL, string strPostdata)
  192. {
  193. ServicePointManager.CertificatePolicy = new CertPolicy();
  194. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
  195. request.CookieContainer = new CookieContainer();
  196. request.Method = "POST";
  197. request.Accept = "*/*";
  198. request.ContentType = "application/x-www-form-urlencoded";
  199. byte[] buffer = this.encoding.GetBytes(strPostdata);
  200. request.ContentLength = buffer.Length;
  201. request.GetRequestStream().Write(buffer, 0, buffer.Length);
  202. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  203. StreamReader reader = new StreamReader(response.GetResponseStream(), encoding);
  204. this.respHtml = reader.ReadToEnd();
  205. foreach (System.Net.Cookie ck in response.Cookies)
  206. {
  207. this.cookie += ck.Name + "=" + ck.Value + ";";
  208. }
  209. reader.Close();
  210. return respHtml;
  211. }
  212. ///<summary>
  213. ///读取指定URL的文本
  214. ///</summary>
  215. ///<param name="URL">请求的地址</param>
  216. ///<param name="postData">向服务器发送的文本数据</param>
  217. ///<returns>服务器响应文本</returns>
  218. public string OpenRead(string URL, string postData)
  219. {
  220. byte[] sendBytes = encoding.GetBytes(postData);
  221. postStream = new MemoryStream();
  222. postStream.Write(sendBytes, 0, sendBytes.Length);
  223. requestHeaders.Add("Content-Length", postStream.Length.ToString());
  224. requestHeaders.Add("Content-Type", "application/x-www-form-urlencoded");
  225. requestHeaders.Add("Connection", "close");
  226. SendRequestData(URL, "POST");
  227. return GetHtml();
  228. }
  229. ///<summary>
  230. ///读取指定URL的流
  231. ///</summary>
  232. ///<param name="URL">请求的地址</param>
  233. ///<param name="postData">向服务器发送的数据</param>
  234. ///<returns>服务器响应流</returns>
  235. public Stream GetStream(string URL, string postData)
  236. {
  237. byte[] sendBytes = encoding.GetBytes(postData);
  238. postStream = new MemoryStream();
  239. postStream.Write(sendBytes, 0, sendBytes.Length);
  240. requestHeaders.Add("Content-Length", postStream.Length.ToString());
  241. requestHeaders.Add("Content-Type", "application/x-www-form-urlencoded");
  242. requestHeaders.Add("Connection", "close");
  243. SendRequestData(URL, "POST");
  244. MemoryStream ms = new MemoryStream();
  245. SaveNetworkStream(ms);
  246. return ms;
  247. }
  248. ///<summary>
  249. ///上传文件到服务器
  250. ///</summary>
  251. ///<param name="URL">请求的地址</param>
  252. ///<param name="fileField">文件域(格式如:file1=C:\test.mp3&file2=C:\test.jpg)</param>
  253. ///<returns>服务器响应文本</returns>
  254. public string UploadFile(string URL, string fileField)
  255. {
  256. return UploadFile(URL, "", fileField);
  257. }
  258. ///<summary>
  259. ///上传文件和数据到服务器
  260. ///</summary>
  261. ///<param name="URL">请求地址</param>
  262. ///<param name="textField">文本域(格式为:name1=value1&name2=value2)</param>
  263. ///<param name="fileField">文件域(格式如:file1=C:\test.mp3&file2=C:\test.jpg)</param>
  264. ///<returns>服务器响应文本</returns>
  265. public string UploadFile(string URL, string textField, string fileField)
  266. {
  267. postStream = new MemoryStream();
  268. if (textField != "" && fileField != "")
  269. {
  270. WriteTextField(textField);
  271. WriteFileField(fileField);
  272. }
  273. else if (fileField != "")
  274. {
  275. WriteFileField(fileField);
  276. }
  277. else if (textField != "")
  278. {
  279. WriteTextField(textField);
  280. }
  281. else
  282. throw new Exception("文本域和文件域不能同时为空。");
  283. //写入结束标记
  284. byte[] buffer = encoding.GetBytes("--" + BOUNDARY + "--\r\n");
  285. postStream.Write(buffer, 0, buffer.Length);
  286. //添加请求标头
  287. requestHeaders.Add("Content-Length", postStream.Length.ToString());
  288. requestHeaders.Add("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
  289. requestHeaders.Add("Connection", "Keep-Alive");
  290. //发送请求数据
  291. SendRequestData(URL, "POST", true);
  292. //返回响应文本
  293. return GetHtml();
  294. }
  295. ///<summary>
  296. ///分析文本域,添加到请求流
  297. ///</summary>
  298. ///<param name="textField">文本域</param>
  299. private void WriteTextField(string textField)
  300. {
  301. string[] strArr = RE.Split(textField, "&");
  302. textField = "";
  303. foreach (string var in strArr)
  304. {
  305. Match M = RE.Match(var, "([^=]+)=(.+)");
  306. textField += "--" + BOUNDARY + "\r\n";
  307. textField += "Content-Disposition: form-data; name=\"" + M.Groups[1].Value + "\"\r\n\r\n" + M.Groups[2].Value + "\r\n";
  308. }
  309. byte[] buffer = encoding.GetBytes(textField);
  310. postStream.Write(buffer, 0, buffer.Length);
  311. }
  312. ///<summary>
  313. ///分析文件域,添加到请求流
  314. ///</summary>
  315. ///<param name="fileField">文件域</param>
  316. private void WriteFileField(string fileField)
  317. {
  318. string filePath = "";
  319. int count = 0;
  320. string[] strArr = RE.Split(fileField, "&");
  321. foreach (string var in strArr)
  322. {
  323. Match M = RE.Match(var, "([^=]+)=(.+)");
  324. filePath = M.Groups[2].Value;
  325. fileField = "--" + BOUNDARY + "\r\n";
  326. fileField += "Content-Disposition: form-data; name=\"" + M.Groups[1].Value + "\"; filename=\"" + Path.GetFileName(filePath) + "\"\r\n";
  327. fileField += "Content-Type: image/jpeg\r\n\r\n";
  328. byte[] buffer = encoding.GetBytes(fileField);
  329. postStream.Write(buffer, 0, buffer.Length);
  330. //添加文件数据
  331. FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  332. buffer = new byte[50000];
  333. do
  334. {
  335. count = fs.Read(buffer, 0, buffer.Length);
  336. postStream.Write(buffer, 0, count);
  337. } while (count > 0);
  338. fs.Close();
  339. fs.Dispose();
  340. fs = null;
  341. buffer = encoding.GetBytes("\r\n");
  342. postStream.Write(buffer, 0, buffer.Length);
  343. }
  344. }
  345. ///<summary>
  346. ///从指定URL下载数据流
  347. ///</summary>
  348. ///<param name="URL">请求地址</param>
  349. ///<returns>数据流</returns>
  350. public Stream DownloadData(string URL)
  351. {
  352. requestHeaders.Add("Connection", "close");
  353. SendRequestData(URL, "GET");
  354. MemoryStream ms = new MemoryStream();
  355. SaveNetworkStream(ms, true);
  356. return ms;
  357. }
  358. ///<summary>
  359. ///从指定URL下载文件
  360. ///</summary>
  361. ///<param name="URL">文件URL地址</param>
  362. ///<param name="fileName">文件保存路径,含文件名(如:C:\test.jpg)</param>
  363. public void DownloadFile(string URL, string fileName)
  364. {
  365. requestHeaders.Add("Connection", "close");
  366. SendRequestData(URL, "GET");
  367. FileStream fs = new FileStream(fileName, FileMode.Create);
  368. SaveNetworkStream(fs, true);
  369. fs.Close();
  370. fs = null;
  371. }
  372. ///<summary>
  373. ///向服务器发送请求
  374. ///</summary>
  375. ///<param name="URL">请求地址</param>
  376. ///<param name="method">POST或GET</param>
  377. ///<param name="showProgress">是否显示上传进度</param>
  378. private void SendRequestData(string URL, string method, bool showProgress)
  379. {
  380. clientSocket = new TcpClient();
  381. Uri URI = new Uri(URL);
  382. clientSocket.Connect(URI.Host, URI.Port);
  383. requestHeaders.Add("Host", URI.Host);
  384. byte[] request = GetRequestHeaders(method + " " + URI.PathAndQuery + " HTTP/1.1");
  385. clientSocket.Client.Send(request);
  386. //若有实体内容就发送它
  387. if (postStream != null)
  388. {
  389. byte[] buffer = new byte[SEND_BUFFER_SIZE];
  390. int count = 0;
  391. Stream sm = clientSocket.GetStream();
  392. postStream.Position = 0;
  393. UploadEventArgs e = new UploadEventArgs();
  394. e.totalBytes = postStream.Length;
  395. System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();//计时器
  396. timer.Start();
  397. do
  398. {
  399. //如果取消就推出
  400. if (isCanceled) { break; }
  401. //读取要发送的数据
  402. count = postStream.Read(buffer, 0, buffer.Length);
  403. //发送到服务器
  404. sm.Write(buffer, 0, count);
  405. //是否显示进度
  406. if (showProgress)
  407. {
  408. //触发事件
  409. e.bytesSent += count;
  410. e.sendProgress = (double)e.bytesSent / (double)e.totalBytes;
  411. double t = timer.ElapsedMilliseconds / 1000;
  412. t = t <= 0 ? 1 : t;
  413. e.sendSpeed = (double)e.bytesSent / t;
  414. if (UploadProgressChanged != null) { UploadProgressChanged(this, e); }
  415. }
  416. } while (count > 0);
  417. timer.Stop();
  418. postStream.Close();
  419. //postStream.Dispose();
  420. postStream = null;
  421. }//end if
  422. }
  423. ///<summary>
  424. ///向服务器发送请求
  425. ///</summary>
  426. ///<param name="URL">请求URL地址</param>
  427. ///<param name="method">POST或GET</param>
  428. private void SendRequestData(string URL, string method)
  429. {
  430. SendRequestData(URL, method, false);
  431. }
  432. ///<summary>
  433. ///获取请求头字节数组
  434. ///</summary>
  435. ///<param name="request">POST或GET请求</param>
  436. ///<returns>请求头字节数组</returns>
  437. private byte[] GetRequestHeaders(string request)
  438. {
  439. requestHeaders.Add("Accept", "*/*");
  440. requestHeaders.Add("Accept-Language", "zh-cn");
  441. requestHeaders.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");
  442. string headers = request + "\r\n";
  443. foreach (string key in requestHeaders)
  444. {
  445. headers += key + ":" + requestHeaders[key] + "\r\n";
  446. }
  447. //有Cookie就带上Cookie
  448. if (cookie != "") { headers += "Cookie:" + cookie + "\r\n"; }
  449. //空行,请求头结束
  450. headers += "\r\n";
  451. strRequestHeaders = headers;
  452. requestHeaders.Clear();
  453. return encoding.GetBytes(headers);
  454. }
  455. ///<summary>
  456. ///获取服务器响应文本
  457. ///</summary>
  458. ///<returns>服务器响应文本</returns>
  459. private string GetHtml()
  460. {
  461. MemoryStream ms = new MemoryStream();
  462. SaveNetworkStream(ms);//将网络流保存到内存流
  463. StreamReader sr = new StreamReader(ms, encoding);
  464. respHtml = sr.ReadToEnd();
  465. sr.Close(); ms.Close();
  466. return respHtml;
  467. }
  468. ///<summary>
  469. ///将网络流保存到指定流
  470. ///</summary>
  471. ///<param name="toStream">保存位置</param>
  472. ///<param name="needProgress">是否显示进度</param>
  473. private void SaveNetworkStream(Stream toStream, bool showProgress)
  474. {
  475. //获取要保存的网络流
  476. NetworkStream NetStream = clientSocket.GetStream();
  477. byte[] buffer = new byte[RECEIVE_BUFFER_SIZE];
  478. int count = 0, startIndex = 0;
  479. MemoryStream ms = new MemoryStream();
  480. for (int i = 0; i < 3; i++)
  481. {
  482. count = NetStream.Read(buffer, 0, 500);
  483. ms.Write(buffer, 0, count);
  484. }
  485. if (ms.Length == 0) { NetStream.Close(); throw new Exception("远程服务器没有响应"); }
  486. buffer = ms.GetBuffer();
  487. count = (int)ms.Length;
  488. GetResponseHeader(buffer, out startIndex);//分析响应,获取响应头和响应实体
  489. count -= startIndex;
  490. toStream.Write(buffer, startIndex, count);
  491. DownloadEventArgs e = new DownloadEventArgs();
  492. if (responseHeaders["Content-Length"] != null)
  493. { e.totalBytes = long.Parse(responseHeaders["Content-Length"]); }
  494. else
  495. { e.totalBytes = -1; }
  496. //启动计时器
  497. System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
  498. timer.Start();
  499. do
  500. {
  501. //如果取消就推出
  502. if (isCanceled) { break; }
  503. //显示下载进度
  504. if (showProgress)
  505. {
  506. e.bytesReceived += count;
  507. e.ReceiveProgress = (double)e.bytesReceived / (double)e.totalBytes;
  508. byte[] tempBuffer = new byte[count];
  509. Array.Copy(buffer, startIndex, tempBuffer, 0, count);
  510. e.receivedBuffer = tempBuffer;
  511. double t = (timer.ElapsedMilliseconds + 0.1) / 1000;
  512. e.receiveSpeed = (double)e.bytesReceived / t;
  513. startIndex = 0;
  514. if (DownloadProgressChanged != null) { DownloadProgressChanged(this, e); }
  515. }
  516. //读取网路数据到缓冲区
  517. count = NetStream.Read(buffer, 0, buffer.Length);
  518. //将缓存区数据保存到指定流
  519. toStream.Write(buffer, 0, count);
  520. } while (count > 0);
  521. timer.Stop();//关闭计时器
  522. if (responseHeaders["Content-Length"] != null)
  523. {
  524. toStream.SetLength(long.Parse(responseHeaders["Content-Length"]));
  525. }
  526. //else
  527. //{
  528. // toStream.SetLength(toStream.Length);
  529. // responseHeaders.Add("Content-Length", toStream.Length.ToString());//添加响应标头
  530. //}
  531. toStream.Position = 0;
  532. //关闭网络流和网络连接
  533. NetStream.Close();
  534. clientSocket.Close();
  535. }
  536. ///<summary>
  537. ///将网络流保存到指定流
  538. ///</summary>
  539. ///<param name="toStream">保存位置</param>
  540. private void SaveNetworkStream(Stream toStream)
  541. {
  542. SaveNetworkStream(toStream, false);
  543. }
  544. ///<summary>
  545. ///分析响应流,去掉响应头
  546. ///</summary>
  547. ///<param name="buffer"></param>
  548. private void GetResponseHeader(byte[] buffer, out int startIndex)
  549. {
  550. responseHeaders.Clear();
  551. string html = encoding.GetString(buffer);
  552. StringReader sr = new StringReader(html);
  553. int start = html.IndexOf("\r\n\r\n") + 4;//找到空行位置
  554. strResponseHeaders = html.Substring(0, start);//获取响应头文本
  555. //获取响应状态码
  556. //
  557. if (sr.Peek() > -1)
  558. {
  559. //读第一行字符串
  560. string line = sr.ReadLine();
  561. //分析此行字符串,获取服务器响应状态码
  562. Match M = RE.Match(line, @"\d\d\d");
  563. if (M.Success)
  564. {
  565. statusCode = int.Parse(M.Value);
  566. }
  567. }
  568. //获取响应头
  569. //
  570. while (sr.Peek() > -1)
  571. {
  572. //读一行字符串
  573. string line = sr.ReadLine();
  574. //若非空行
  575. if (line != "")
  576. {
  577. //分析此行字符串,获取响应标头
  578. Match M = RE.Match(line, "([^:]+):(.+)");
  579. if (M.Success)
  580. {
  581. try
  582. { //添加响应标头到集合
  583. responseHeaders.Add(M.Groups[1].Value.Trim(), M.Groups[2].Value.Trim());
  584. }
  585. catch
  586. { }
  587. //获取Cookie
  588. if (M.Groups[1].Value == "Set-Cookie")
  589. {
  590. M = RE.Match(M.Groups[2].Value, "[^=]+=[^;]+");
  591. cookie += M.Value.Trim() + ";";
  592. }
  593. }
  594. }
  595. //若是空行,代表响应头结束响应实体开始。(响应头和响应实体间用一空行隔开)
  596. else
  597. {
  598. //如果响应头中没有实体大小标头,尝试读响应实体第一行获取实体大小
  599. if (responseHeaders["Content-Length"] == null && sr.Peek() > -1)
  600. {
  601. //读响应实体第一行
  602. line = sr.ReadLine();
  603. //分析此行看是否包含实体大小
  604. Match M = RE.Match(line, "~[0-9a-fA-F]{1,15}");
  605. if (M.Success)
  606. {
  607. //将16进制的实体大小字符串转换为10进制
  608. int length = int.Parse(M.Value, System.Globalization.NumberStyles.AllowHexSpecifier);
  609. responseHeaders.Add("Content-Length", length.ToString());//添加响应标头
  610. strResponseHeaders += M.Value + "\r\n";
  611. }
  612. }
  613. break;//跳出循环
  614. }//End If
  615. }//End While
  616. sr.Close();
  617. //实体开始索引
  618. startIndex = encoding.GetBytes(strResponseHeaders).Length;
  619. }
  620. ///<summary>
  621. ///取消上传或下载,要继续开始请调用Start方法
  622. ///</summary>
  623. public void Cancel()
  624. {
  625. isCanceled = true;
  626. }
  627. ///<summary>
  628. ///启动上传或下载,要取消请调用Cancel方法
  629. ///</summary>
  630. public void Start()
  631. {
  632. isCanceled = false;
  633. }
  634. //*************************************************************
  635. //以下为属性
  636. //*************************************************************
  637. ///<summary>
  638. ///获取或设置请求头
  639. ///</summary>
  640. public WebHeaderCollection RequestHeaders
  641. {
  642. set { requestHeaders = value; }
  643. get { return requestHeaders; }
  644. }
  645. ///<summary>
  646. ///获取响应头集合
  647. ///</summary>
  648. public WebHeaderCollection ResponseHeaders
  649. {
  650. get { return responseHeaders; }
  651. }
  652. ///<summary>
  653. ///获取请求头文本
  654. ///</summary>
  655. public string StrRequestHeaders
  656. {
  657. get { return strRequestHeaders; }
  658. }
  659. ///<summary>
  660. ///获取响应头文本
  661. ///</summary>
  662. public string StrResponseHeaders
  663. {
  664. get { return strResponseHeaders; }
  665. }
  666. ///<summary>
  667. ///获取或设置Cookie
  668. ///</summary>
  669. public string Cookie
  670. {
  671. set { cookie = value; }
  672. get { return cookie; }
  673. }
  674. ///<summary>
  675. ///获取或设置编码方式(默认为系统默认编码方式)
  676. ///</summary>
  677. public Encoding Encoding
  678. {
  679. set { encoding = value; }
  680. get { return encoding; }
  681. }
  682. ///<summary>
  683. ///获取服务器响应文本
  684. ///</summary>
  685. public string RespHtml
  686. {
  687. get { return respHtml; }
  688. }
  689. ///<summary>
  690. ///获取服务器响应状态码
  691. ///</summary>
  692. public int StatusCode
  693. {
  694. get { return statusCode; }
  695. }
  696. }
  697. }  

大部分转载 小部分自写