HTTP发送请求模拟
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 }