using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Net;
using System.Web;
namespace Deerchao.Utility
{
public class HttpClient
{
#region fields
private bool keepContext;
private string defaultLanguage = "zh-CN";
private string defaultEncoding = "utf-8";
private string accept = "*/*";
private string userAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
private HttpVerb verb;
private WebContext context;
private readonly List<HttpUploadingFile> files = new List<HttpUploadingFile>();
private readonly Dictionary<string, string> postingData = new Dictionary<string, string>();
private string url;
private WebHeaderCollection responseHeaders;
#endregion
#region property
public bool KeepContext
{
get { return keepContext; }
set { keepContext = value; }
}
public string DefaultLanguage
{
get { return defaultLanguage; }
set { defaultLanguage = value; }
}
public string DefaultEncoding
{
get { return defaultEncoding; }
set { defaultEncoding = value; }
}
public HttpVerb Verb
{
get { return verb; }
set { verb = value; }
}
public List<HttpUploadingFile> Files
{
get { return files; }
}
public Dictionary<string, string> PostingData
{
get { return postingData; }
}
public string Url
{
get { return url; }
set { url = value; }
}
public WebHeaderCollection ResponseHeaders
{
get { return responseHeaders; }
}
public string Accept
{
get { return accept; }
set { accept = value; }
}
public string UserAgent
{
get { return userAgent; }
set { userAgent = value; }
}
public WebContext Context
{
get { return context; }
set { context = value; }
}
#endregion
#region constructor
public HttpClient()
{
}
public HttpClient(string url)
: this(url, null)
{
}
public HttpClient(string url, WebContext context)
: this(url, context, false)
{
}
public HttpClient(string url, WebContext context, bool keepContext)
{
this.url = url;
this.context = context;
this.keepContext = keepContext;
}
#endregion
public void AttachFile(string fileName, string fieldName)
{
HttpUploadingFile file = new HttpUploadingFile(fileName, fieldName);
files.Add(file);
}
public void AttachFile(byte[] data, string fileName, string fieldName)
{
HttpUploadingFile file = new HttpUploadingFile(data, fileName, fieldName);
files.Add(file);
}
public void ClearLastRequestInfo()
{
verb = HttpVerb.GET;
files.Clear();
postingData.Clear();
responseHeaders = null;
url = null;
}
private HttpWebRequest CreateRequest()
{
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url);
req.AllowAutoRedirect = false;
req.CookieContainer = new CookieContainer();
req.Headers.Add("Accept-Language", defaultLanguage);
req.Accept = accept;
req.UserAgent = userAgent;
req.KeepAlive = false;
if (context != null)
{
if (context.Cookies != null)
req.CookieContainer.Add(context.Cookies);
if (!string.IsNullOrEmpty(context.Referer))
req.Referer = context.Referer;
}
if (postingData.Count > 0 || files.Count > 0)
verb = HttpVerb.POST;
if (verb == HttpVerb.POST)
{
req.Method = "POST";
MemoryStream memoryStream = new MemoryStream();
StreamWriter writer = new StreamWriter(memoryStream);
if (files.Count > 0)
{
string newLine = "\r\n";
string boundary = Guid.NewGuid().ToString().Replace("-", "");
req.ContentType = "multipart/form-data; boundary=" + boundary;
foreach (string key in postingData.Keys)
{
writer.Write("--" + boundary + newLine);
writer.Write("Content-Disposition: form-data; name=\"{0}\"{1}{1}", key, newLine);
writer.Write(postingData[key] + newLine);
}
foreach (HttpUploadingFile file in files)
{
writer.Write("--" + boundary + newLine);
writer.Write(
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}",
file.FieldName,
file.FileName,
newLine
);
writer.Write("Content-Type: application/octet-stream" + newLine + newLine);
writer.Flush();
memoryStream.Write(file.Data, 0, file.Data.Length);
writer.Write(newLine);
}
}
else
{
req.ContentType = "application/x-www-form-urlencoded";
StringBuilder sb = new StringBuilder();
foreach (string key in postingData.Keys)
{
sb.AppendFormat("{0}={1}&", key, postingData[key]);
}
if (sb.Length > 0)
sb.Length--;
writer.Write(HttpUtility.UrlEncode(sb.ToString()));
}
writer.Flush();
using (Stream stream = req.GetRequestStream())
{
memoryStream.WriteTo(stream);
}
}
return req;
}
public HttpWebResponse GetResponse()
{
HttpWebRequest req = CreateRequest();
HttpWebResponse res = (HttpWebResponse) req.GetResponse();
responseHeaders = res.Headers;
if (keepContext)
{
if (context == null)
context = new WebContext();
context.Cookies = res.Cookies;
context.Referer = url;
}
return res;
}
public Stream GetStream()
{
return GetResponse().GetResponseStream();
}
public byte[] GetBytes()
{
HttpWebResponse res = GetResponse();
MemoryStream memoryStream = new MemoryStream();
byte[] buffer = new byte[0x400];
Stream rs = res.GetResponseStream();
for (int i = rs.Read(buffer, 0, buffer.Length); i > 0; i = rs.Read(buffer, 0, buffer.Length))
{
memoryStream.Write(buffer, 0, i);
}
rs.Close();
return memoryStream.ToArray();
}
public string GetString()
{
byte[] data = GetBytes();
string encoding = GetEncodingFromHeaders();
if (encoding == null)
encoding = GetEncodingFromBody(data);
if (encoding == null)
encoding = defaultEncoding;
Encoding actualEncoding;
try
{
actualEncoding = Encoding.GetEncoding(encoding);
}
catch
{
actualEncoding = Encoding.GetEncoding(defaultEncoding);
}
return actualEncoding.GetString(data);
}
private string GetEncodingFromHeaders()
{
string encoding = null;
string contentType = responseHeaders["content-type"];
if (contentType != null)
{
int i = contentType.IndexOf("charset=");
if (i != -1)
{
encoding = contentType.Substring(i + 8);
}
}
return encoding;
}
private string GetEncodingFromBody(byte[] data)
{
string encoding = null;
string dataAsAscii = Encoding.ASCII.GetString(data);
if (dataAsAscii != null)
{
int i = dataAsAscii.IndexOf("charset=");
if (i != -1)
{
int j = dataAsAscii.IndexOf("\"", i);
if (j != -1)
{
int k = i + 8;
encoding = dataAsAscii.Substring(k, (j - k) + 1);
char[] chArray = new char[2] { '>', '"' };
encoding = encoding.TrimEnd(chArray);
}
}
}
return encoding;
}
public void SaveAsFile(string fileName)
{
using (BinaryWriter writer = new BinaryWriter(new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)))
writer.Write(GetBytes());
}
}
public class WebContext
{
private CookieCollection cookies;
private string referer;
public CookieCollection Cookies
{
get { return cookies; }
set { cookies = value; }
}
public string Referer
{
get { return referer; }
set { referer = value; }
}
}
public enum HttpVerb
{
GET,
POST,
}
public class HttpUploadingFile
{
private string fileName;
private string fieldName;
private byte[] data;
public string FileName
{
get { return fileName; }
set { fileName = value; }
}
public string FieldName
{
get { return fieldName; }
set { fieldName = value; }
}
public byte[] Data
{
get { return data; }
set { data = value; }
}
public HttpUploadingFile(string fileName, string fieldName)
{
this.fileName = fileName;
this.fieldName = fieldName;
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
byte[] inBytes = new byte[stream.Length];
stream.Read(inBytes, 0, inBytes.Length);
data = inBytes;
}
}
public HttpUploadingFile(byte[] data, string fileName, string fieldName)
{
this.data = data;
this.fileName = fileName;
this.fieldName = fieldName;
}
}
}