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