using System;
using System.Net;
using System.Web;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
namespace Rocky.Net
{
public class HttpWalker
{
#region StaticMembers
public static void DownloadFile(HttpContext context, string filePath)
{
AppRuntime.Guard<ArgumentNullException>(context == null);
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
Response.Clear();
Response.Buffer = false;
Response.AddHeader("Accept-Ranges", "bytes");
using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] buffer = BufferUtility.GetBuffer((int)stream.Length);
long p = 0L, l = stream.Length;
#region Resolve Range
string range = Request.Headers["Range"];
if (range != null)
{
//Range:bytes=1024-
//Range:bytes=1024-2048
//Range:bytes=-1024
//Range:bytes=0-512,1024-2048
int index = range.IndexOf("=");
if (index != -1)
{
string[] ranges = range.Substring(index + 1).Split(',');
if (ranges.Length > 1)
{
//not supported multipart/byterange
}
else
{
bool flag = false;
if (ranges[0].StartsWith("-"))
{
long _p, _absp;
if (long.TryParse(ranges[0], out _p) && (_absp = Math.Abs(_p)) <= l)
{
if (_p < 0)
{
p = l - _absp;
l = _absp;
flag = true;
}
}
}
else
{
ranges = ranges[0].Split('-');
if (ranges.Length == 2)
{
long _p, _l;
if (ranges[1] == string.Empty)
{
if (long.TryParse(ranges[0], out _p) && _p <= l)
{
p = _p;
flag = true;
}
}
else if (long.TryParse(ranges[0], out _p) && long.TryParse(ranges[1], out _l) && _p > 0 && _l > 0 && _p < _l && _l < l)
{
p = _p;
l = _l + 1;
flag = true;
}
}
}
if (flag)
{
Response.StatusCode = 206;
Response.AddHeader("Content-Range", "bytes " + p.ToString() + "-" + l.ToString() + "/" + stream.Length.ToString());
}
else
{
Response.StatusCode = 416; //Requested range not satisfiable
}
}
}
}
#endregion
Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(Path.GetFileName(filePath), Encoding.UTF8));
Response.AddHeader("Content-Length", l.ToString());
Response.ContentType = "application/octet-stream";
stream.Position = p;
int read;
while (Response.IsClientConnected && p < l)
{
Response.OutputStream.Write(buffer, 0, read = stream.Read(buffer, 0, buffer.Length));
Response.Flush();
p += read;
}
}
Response.End();
}
public static void UploadFile(HttpContext context, string savePath)
{
AppRuntime.Guard<ArgumentNullException>(context == null);
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
string msg = "0", fileName = Request.Headers["filename"];
if (fileName != null)
{
FileInfo file = new FileInfo(Path.Combine(Path.GetDirectoryName(savePath), fileName));
if (Request.Headers["breakpoint"] == bool.TrueString)
{
Response.AddHeader("Content-Length", (file.Exists ? file.Length : 0L).ToString());
}
else
{
long l;
if (Request.Files.Count > 0 && long.TryParse(Request.Headers["breakpoint"], out l))
{
HttpPostedFile postedFile = Request.Files[0];
using (FileStream stream = file.Open(file.Exists ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.None))
{
byte[] buffer = BufferUtility.GetBuffer((int)stream.Length);
Stream postedStream = postedFile.InputStream;
long p = stream.Position;
int read;
while (Response.IsClientConnected && p < l)
{
stream.Write(buffer, 0, read = postedStream.Read(buffer, 0, buffer.Length));
stream.Flush();
p += read;
}
}
file.MoveTo(savePath);
msg = "1";
}
}
}
Response.Write(msg);
Response.End();
}
#endregion
#region Fields
private HttpWebRequest httpRequest;
private CookieContainer cookieContainer;
private string referer;
private NameValueCollection form;
private List<HttpFile> files;
#endregion
#region Properties
public Uri RequestUri
{
set { httpRequest = (HttpWebRequest)WebRequest.Create(value); }
get { return httpRequest.RequestUri; }
}
public HttpWebRequest Request
{
get { return httpRequest; }
}
public CookieCollection Cookies
{
get { return cookieContainer.GetCookies(httpRequest.RequestUri); }
}
public NameValueCollection Form
{
get
{
if (form == null)
{
form = new NameValueCollection();
}
return form;
}
}
public List<HttpFile> Files
{
get
{
if (files == null)
{
files = new List<HttpFile>();
}
return files;
}
}
#endregion
#region Constructor
public HttpWalker(Uri uri)
{
this.RequestUri = uri;
cookieContainer = new CookieContainer();
referer = "http://www.google.com";
}
#endregion
#region Methods
public long GetContentLengthByHead()
{
return GetContentLengthByHead(true);
}
public long GetContentLengthByHead(bool reset)
{
using (HttpWebResponse httpResponse = GetResponse(WebRequestMethods.Http.Head))
{
if (reset)
{
httpRequest = (HttpWebRequest)WebRequest.Create(httpRequest.RequestUri);
}
return httpResponse.ContentLength;
}
}
public HttpWebResponse GetResponse()
{
if ((form != null && form.Count > 0) || (files != null && files.Count > 0))
{
return GetResponse(WebRequestMethods.Http.Post);
}
else
{
return GetResponse(WebRequestMethods.Http.Get);
}
}
public HttpWebResponse GetResponse(string method)
{
if (httpRequest.RequestUri.Scheme == "https")
{
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);
}
httpRequest.CookieContainer = cookieContainer;
httpRequest.Referer = referer;
httpRequest.Accept = "*/*";
httpRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
if ((httpRequest.Method = method) == WebRequestMethods.Http.Post)
{
StringBuilder sb = new StringBuilder();
if (files.Count > 0)
{
Queue methodQueue = new Queue();
string boundary = Guid.NewGuid().ToString().Replace("-", string.Empty), line = "\r\n";
byte[] beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + line);
//byte[] endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--" + newLine);
httpRequest.ContentType = "multipart/form-data; boundary=" + boundary;
long contentLength = 0L;
if (form != null && form.Count > 0)
{
for (int i = 0; i < form.Count; i++)
{
sb.Length = 0;
sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n", form.GetKey(i));
sb.AppendFormat("{0}\r\n", form.Get(i));
byte[] header = Encoding.UTF8.GetBytes(sb.ToString());
contentLength += beginBoundary.LongLength + header.LongLength;
methodQueue.Enqueue(new Action<Stream>(stream =>
{
stream.Write(beginBoundary, 0, beginBoundary.Length);
stream.Write(header, 0, header.Length);
}));
}
}
if (files != null)
{
sb.Length = 0;
sb.Append(line);
sb.Append("--" + boundary + line);
byte[] endOfFile = Encoding.ASCII.GetBytes(sb.ToString());
files.ForEach(file =>
{
sb.Length = 0;
sb.AppendFormat("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n", file.FieldName, Path.GetFileName(file.FileName));
sb.Append("Content-Type: application/octet-stream\r\n\r\n");
byte[] header = Encoding.UTF8.GetBytes(sb.ToString());
contentLength += beginBoundary.LongLength + header.LongLength + file.ContentLength + endOfFile.LongLength;
methodQueue.Enqueue(new Action<Stream>(stream =>
{
stream.Write(beginBoundary, 0, beginBoundary.Length);
stream.Write(header, 0, header.Length);
file.WriteTo(stream);
stream.Write(endOfFile, 0, endOfFile.Length);
}));
});
}
httpRequest.ContentLength = contentLength;
Stream requestStream = httpRequest.GetRequestStream();
while (methodQueue.Count > 0)
{
((Action<Stream>)methodQueue.Dequeue())(requestStream);
}
requestStream.Close();
}
else
{
if (form != null && form.Count > 0)
{
httpRequest.ContentType = "application/x-www-form-urlencoded";
sb.Append(form.GetKey(0)).Append("=").Append(form.Get(0));
for (int i = 1; i < form.Count; i++)
{
sb.Append("&").Append(form.GetKey(i)).Append("=").Append(form.Get(i));
}
byte[] data = Encoding.UTF8.GetBytes(sb.ToString());
httpRequest.ContentLength = data.LongLength;
Stream requestStream = httpRequest.GetRequestStream();
requestStream.Write(data, 0, data.Length);
requestStream.Close();
}
}
}
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
referer = httpResponse.ResponseUri.AbsoluteUri;
return httpResponse;
}
//https
private bool CheckValidationResult(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors errors)
{
// Always accept
return true;
}
public void Reset(Uri uri)
{
this.RequestUri = uri;
cookieContainer = new CookieContainer();
referer = "http://www.google.com";
if (form != null)
{
form.Clear();
}
if (files != null)
{
files.Clear();
}
}
public void RefreshCookies()
{
cookieContainer = new CookieContainer();
}
public override string ToString()
{
HttpWebResponse httpResponse = GetResponse();
using (StreamReader reader = new StreamReader(httpResponse.GetResponseStream(), Encoding.GetEncoding(httpResponse.CharacterSet ?? "gb2312")))
{
return reader.ReadToEnd();
}
}
#endregion
#region File
public void DownloadFile(string savePath)
{
using (FileStream stream = new FileStream(savePath, File.Exists(savePath) ? FileMode.Append : FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
httpRequest.AddRange((int)stream.Length);
HttpWebResponse response = GetResponse();
byte[] buffer = new byte[BufferUtility.FileBufferSize];
Stream responseStream = response.GetResponseStream();
long p = stream.Length, l = response.ContentLength;
请发表评论