迷你型WebClient


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

使用实例:

  1.    class Test
  2.     {
  3.         public static void Test1()
  4.         {
  5.             HttpProc.WebClient c = new HttpProc.WebClient();
  6.             c.DownloadProgressChanged += new EventHandler(c_DownloadProgressChanged);
  7.             c.UploadProgressChanged += new EventHandler(c_UploadProgressChanged);
  8.             
  9.             //登录百度空间
  10.             c.Post("https://passport.baidu.com/?login""username=hddo&password=**********");
  11.             if (c.RespHtml.Contains("passport.baidu.com"))
  12.             {
  13.                 //登录成功
  14.             }
  15.             //向百度相册上传图片
  16.             HttpProc.MultipartForm mf = new HttpProc.MultipartForm();
  17.             mf.AddString("BrowserType""1");
  18.             mf.AddString("spPhotoText0""10086");
  19.             mf.AddString("spAlbumName""默认相册");
  20.             mf.AddString("spMaxSize""1600");
  21.             mf.AddString("spQuality""90");
  22.             mf.AddFlie("file1""D://Blue hills2.jpg");
  23.             c.Post("http://hiup.baidu.com/hddo/upload", mf);
  24.             if (c.RespHtml.Contains("submit(0,0)"))
  25.             {
  26.                 //上传图片成功
  27.             }
  28.         }
  29.         static void c_UploadProgressChanged(object sender, HttpProc.UploadEventArgs e)
  30.         {
  31.             //显示上传进度
  32.         }
  33.         static void c_DownloadProgressChanged(object sender, HttpProc.DownloadEventArgs e)
  34.         {
  35.             //显示下载进度
  36.         }
  37.     }

 

你可能感兴趣的:(.NET,HTTP)