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