对HttpWebRequest/HttpWebResponse 进行封装处理,提供方便的接口向互联网发送或接收数据。支持POST urlencode形式的字符串以及mulitpart/form-data形式的二进制或文本数据,支持GET方式获取数据。自动管理Cookie,解 决网络访问中难以处理的权限问题。支持gzip,deflate编码数据解压。测试代码见代码后面。
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.IO.Compression;
using System.Net.Cache;
namespace HttpProc
{
/// <summary>
/// 上传数据参数
/// </summary>
public class UploadEventArgs : EventArgs
{
int bytesSent;
int totalBytes;
/// <summary>
/// 已发送的字节数
/// </summary>
public int BytesSent
{
get { return bytesSent; }
set { bytesSent = value; }
}
/// <summary>
/// 总字节数
/// </summary>
public int TotalBytes
{
get { return totalBytes; }
set { totalBytes = value; }
}
}
/// <summary>
/// 下载数据参数
/// </summary>
public class DownloadEventArgs : EventArgs
{
int bytesReceived;
int totalBytes;
byte[] receivedData;
/// <summary>
/// 已接收的字节数
/// </summary>
public int BytesReceived
{
get { return bytesReceived; }
set { bytesReceived = value; }
}
/// <summary>
/// 总字节数
/// </summary>
public int TotalBytes
{
get { return totalBytes; }
set { totalBytes = value; }
}
/// <summary>
/// 当前缓冲区接收的数据
/// </summary>
public byte[] ReceivedData
{
get { return receivedData; }
set { receivedData = value; }
}
}
public class WebClient
{
Encoding encoding = Encoding.Default;
string respHtml = "";
WebProxy proxy;
static CookieContainer cc;
WebHeaderCollection requestHeaders;
WebHeaderCollection responseHeaders;
int bufferSize = 15240;
public event EventHandler<UploadEventArgs> UploadProgressChanged;
public event EventHandler<DownloadEventArgs> DownloadProgressChanged;
static WebClient()
{
LoadCookiesFromDisk();
}
/// <summary>
/// 创建WebClient的实例
/// </summary>
public WebClient()
{
requestHeaders = new WebHeaderCollection();
responseHeaders = new WebHeaderCollection();
}
/// <summary>
/// 设置发送和接收的数据缓冲大小
/// </summary>
public int BufferSize
{
get { return bufferSize; }
set { bufferSize = value; }
}
/// <summary>
/// 获取响应头集合
/// </summary>
public WebHeaderCollection ResponseHeaders
{
get { return responseHeaders; }
}
/// <summary>
/// 获取请求头集合
/// </summary>
public WebHeaderCollection RequestHeaders
{
get { return requestHeaders; }
}
/// <summary>
/// 获取或设置代理
/// </summary>
public WebProxy Proxy
{
get { return proxy; }
set { proxy = value; }
}
/// <summary>
/// 获取或设置请求与响应的文本编码方式
/// </summary>
public Encoding Encoding
{
get { return encoding; }
set { encoding = value; }
}
/// <summary>
/// 获取或设置响应的html代码
/// </summary>
public string RespHtml
{
get { return respHtml; }
set { respHtml = value; }
}
/// <summary>
/// 获取或设置与请求关联的Cookie容器
/// </summary>
public CookieContainer CookieContainer
{
get { return cc; }
set { cc = value; }
}
/// <summary>
/// 获取网页源代码
/// </summary>
/// <param name="url">网址</param>
/// <returns></returns>
public string GetHtml(string url)
{
HttpWebRequest request = CreateRequest(url, "GET");
respHtml = encoding.GetString(GetData(request));
return respHtml;
}
/// <summary>
/// 下载文件
/// </summary>
/// <param name="url">文件URL地址</param>
/// <param name="filename">文件保存完整路径</param>
public void DownloadFile(string url, string filename)
{
FileStream fs = null;
try
{
HttpWebRequest request = CreateRequest(url, "GET");
byte[] data = GetData(request);
fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
fs.Write(data, 0, data.Length);
}
finally
{
if (fs != null) fs.Close();
}
}
/// <summary>
/// 从指定URL下载数据
/// </summary>
/// <param name="url">网址</param>
/// <returns></returns>
public byte[] GetData(string url)
{
HttpWebRequest request = CreateRequest(url, "GET");
return GetData(request);
}
/// <summary>
/// 向指定URL发送文本数据
/// </summary>
/// <param name="url">网址</param>
/// <param name="postData">urlencode编码的文本数据</param>
/// <returns></returns>
public string Post(string url, string postData)
{
byte[] data = encoding.GetBytes(postData);
return Post(url, data);
}
/// <summary>
/// 向指定URL发送字节数据
/// </summary>
/// <param name="url">网址</param>
/// <param name="postData">发送的字节数组</param>
/// <returns></returns>
public string Post(string url, byte[] postData)
{
HttpWebRequest request = CreateRequest(url, "POST");
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.Length;
request.KeepAlive = true;
PostData(request, postData);
respHtml = encoding.GetString(GetData(request));
return respHtml;
}
/// <summary>
/// 向指定网址发送mulitpart编码的数据
/// </summary>
/// <param name="url">网址</param>
/// <param name="mulitpartForm">mulitpart form data</param>
/// <returns></returns>
public string Post(string url, MultipartForm mulitpartForm)
{
HttpWebRequest request = CreateRequest(url, "POST");
request.ContentType = mulitpartForm.ContentType;
request.ContentLength = mulitpartForm.FormData.Length;
request.KeepAlive = true;
PostData(request, mulitpartForm.FormData);
respHtml = encoding.GetString(GetData(request));
return respHtml;
}
/// <summary>
/// 读取请求返回的数据
/// </summary>
/// <param name="request">请求对象</param>
/// <returns></returns>
private byte[] GetData(HttpWebRequest request)
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
responseHeaders = response.Headers;
SaveCookiesToDisk();
DownloadEventArgs args = new DownloadEventArgs();
if (responseHeaders[HttpResponseHeader.ContentLength] != null)
args.TotalBytes = Convert.ToInt32(responseHeaders[HttpResponseHeader.ContentLength]);
MemoryStream ms = new MemoryStream();
int count = 0;
byte[] buf = new byte[bufferSize];
while ((count = stream.Read(buf, 0, buf.Length)) > 0)
{
ms.Write(buf, 0, count);
if (this.DownloadProgressChanged != null)
{
args.BytesReceived += count;
args.ReceivedData = new byte[count];
Array.Copy(buf, args.ReceivedData, count);
this.DownloadProgressChanged(this, args);
}
}
stream.Close();
//解压
if (ResponseHeaders[HttpResponseHeader.ContentEncoding] != null)
{
MemoryStream msTemp = new MemoryStream();
count = 0;
buf = new byte[100];
switch (ResponseHeaders[HttpResponseHeader.ContentEncoding].ToLower())
{
case "gzip":
GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress);
while ((count = gzip.Read(buf, 0, buf.Length)) > 0)
{
msTemp.Write(buf, 0, count);
}
return msTemp.ToArray();
case "deflate":
DeflateStream deflate = new DeflateStream(ms, CompressionMode.Decompress);
while ((count = deflate.Read(buf, 0, buf.Length)) > 0)
{
msTemp.Write(buf, 0, count);
}
return msTemp.ToArray();
default:
break;
}
}
return ms.ToArray();
}
/// <summary>
/// 发送请求数据
/// </summary>
/// <param name="request">请求对象</param>
/// <param name="postData">请求发送的字节数组</param>
private void PostData(HttpWebRequest request, byte[] postData)
{
int offset = 0;
int sendBufferSize = bufferSize;
int remainBytes = 0;
Stream stream = request.GetRequestStream();
UploadEventArgs args = new UploadEventArgs();
args.TotalBytes = postData.Length;
while ((remainBytes = postData.Length - offset) > 0)
{
if (sendBufferSize > remainBytes) sendBufferSize = remainBytes;
stream.Write(postData, offset, sendBufferSize);
offset += sendBufferSize;
if (this.UploadProgressChanged != null)
{
args.BytesSent = offset;
this.UploadProgressChanged(this, args);
}
}
stream.Close();
}
/// <summary>
/// 创建HTTP请求
/// </summary>
/// <param name="url">URL地址</param>
/// <returns></returns>
private HttpWebRequest CreateRequest(string url, string method)
{
Uri uri = new Uri(url);
if (uri.Scheme == "https")
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(this.CheckValidationResult);
// Set a default policy level for the "http:" and "https" schemes.
HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Revalidate);
HttpWebRequest.DefaultCachePolicy = policy;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AllowAutoRedirect = false;
request.AllowWriteStreamBuffering = false;
request.Method = method;
if (proxy != null) request.Proxy = proxy;
request.CookieContainer = cc;
foreach (string key in requestHeaders.Keys)
{
request.Headers.Add(key, requestHeaders[key]);
}
requestHeaders.Clear();
return request;
}
private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
}
/// <summary>
/// 将Cookie保存到磁盘
/// </summary>
private static void SaveCookiesToDisk()
{
string cookieFile = System.Environment.GetFolderPath(Environment.SpecialFolder.Cookies) + "\\webclient.cookie";
FileStream fs = null;
try
{
fs = new FileStream(cookieFile, FileMode.Create);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formater = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
formater.Serialize(fs, cc);
}
finally
{
if (fs != null) fs.Close();
}
}
/// <summary>
/// 从磁盘加载Cookie
/// </summary>
private static void LoadCookiesFromDisk()
{
cc = new CookieContainer();
string cookieFile = System.Environment.GetFolderPath(Environment.SpecialFolder.Cookies) + "\\webclient.cookie";
if (!File.Exists(cookieFile))
return;
FileStream fs = null;
try
{
fs = new FileStream(cookieFile, FileMode.Open, FileAccess.Read, FileShare.Read);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formater = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
cc = (CookieContainer)formater.Deserialize(fs);
}
finally
{
if (fs != null) fs.Close();
}
}
}
/// <summary>
/// 对文件和文本数据进行Multipart形式的编码
/// </summary>
public class MultipartForm
{
private Encoding encoding;
private MemoryStream ms;
private string boundary;
private byte[] formData;
/// <summary>
/// 获取编码后的字节数组
/// </summary>
public byte[] FormData
{
get
{
if (formData == null)
{
byte[] buffer = encoding.GetBytes("--" + this.boundary + "--\r\n");
ms.Write(buffer, 0, buffer.Length);
formData = ms.ToArray();
}
return formData;
}
}
/// <summary>
/// 获取此编码内容的类型
/// </summary>
public string ContentType
{
get { return string.Format("multipart/form-data; boundary={0}", this.boundary); }
}
/// <summary>
/// 获取或设置对字符串采用的编码类型
/// </summary>
public Encoding StringEncoding
{
set { encoding = value; }
get { return encoding; }
}
/// <summary>
/// 实例化
/// </summary>
public MultipartForm()
{
boundary = string.Format("--{0}--", Guid.NewGuid());
ms = new MemoryStream();
encoding = Encoding.Default;
}
/// <summary>
/// 添加一个文件
/// </summary>
/// <param name="name">文件域名称</param>
/// <param name="filename">文件的完整路径</param>
public void AddFlie(string name, string filename)
{
if (!File.Exists(filename))
throw new FileNotFoundException("尝试添加不存在的文件。", filename);
FileStream fs = null;
byte[] fileData ={ };
try
{
fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
fileData = new byte[fs.Length];
fs.Read(fileData, 0, fileData.Length);
this.AddFlie(name, Path.GetFileName(filename), fileData, fileData.Length);
}
catch (Exception)
{
throw;
}
finally
{
if (fs != null) fs.Close();
}
}
/// <summary>
/// 添加一个文件
/// </summary>
/// <param name="name">文件域名称</param>
/// <param name="filename">文件名</param>
/// <param name="fileData">文件二进制数据</param>
/// <param name="dataLength">二进制数据大小</param>
public void AddFlie(string name, string filename, byte[] fileData, int dataLength)
{
if (dataLength <= 0 || dataLength > fileData.Length)
{
dataLength = fileData.Length;
}
StringBuilder sb = new StringBuilder();
sb.AppendFormat("--{0}\r\n", this.boundary);
sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\n", name, filename);
sb.AppendFormat("Content-Type: {0}\r\n", this.GetContentType(filename));
sb.Append("\r\n");
byte[] buf = encoding.GetBytes(sb.ToString());
ms.Write(buf, 0, buf.Length);
ms.Write(fileData, 0, dataLength);
byte[] crlf = encoding.GetBytes("\r\n");
ms.Write(crlf, 0, crlf.Length);
}
/// <summary>
/// 添加字符串
/// </summary>
/// <param name="name">文本域名称</param>
/// <param name="value">文本值</param>
public void AddString(string name, string value)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("--{0}\r\n", this.boundary);
sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\"\r\n", name);
sb.Append("\r\n");
sb.AppendFormat("{0}\r\n", value);
byte[] buf = encoding.GetBytes(sb.ToString());
ms.Write(buf, 0, buf.Length);
}
/// <summary>
/// 从注册表获取文件类型
/// </summary>
/// <param name="filename">包含扩展名的文件名</param>
/// <returns>如:application/stream</returns>
private string GetContentType(string filename)
{
Microsoft.Win32.RegistryKey fileExtKey = null; ;
string contentType = "application/stream";
try
{
fileExtKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(Path.GetExtension(filename));
contentType = fileExtKey.GetValue("Content Type", contentType).ToString();
}
finally
{
if (fileExtKey != null) fileExtKey.Close();
}
return contentType;
}
}
}
使用实例:
class Test
{
public static void Test1()
{
HttpProc.WebClient c = new HttpProc.WebClient();
c.DownloadProgressChanged += new EventHandler<HttpProc.DownloadEventArgs>(c_DownloadProgressChanged);
c.UploadProgressChanged += new EventHandler<HttpProc.UploadEventArgs>(c_UploadProgressChanged);
//登录百度空间
c.Post("https://passport.baidu.com/?login", "username=hddo&password=**********");
if (c.RespHtml.Contains("passport.baidu.com"))
{
//登录成功
}
//向百度相册上传图片
HttpProc.MultipartForm mf = new HttpProc.MultipartForm();
mf.AddString("BrowserType", "1");
mf.AddString("spPhotoText0", "10086");
mf.AddString("spAlbumName", "默认相册");
mf.AddString("spMaxSize", "1600");
mf.AddString("spQuality", "90");
mf.AddFlie("file1", "D:\\Blue hills2.jpg");
c.Post("http://hiup.baidu.com/hddo/upload", mf);
if (c.RespHtml.Contains("submit(0,0)"))
{
//上传图片成功
}
}
static void c_UploadProgressChanged(object sender, HttpProc.UploadEventArgs e)
{
//显示上传进度
}
static void c_DownloadProgressChanged(object sender, HttpProc.DownloadEventArgs e)
{
//显示下载进度
}
}