ProxyConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class ProxyConfig
{
public static ProxyConfig DefaultProxy;
public string Host { get; set; }
public int Port { get; set; }
public string Account { get; set; }
public string Password { get; set; }
public ProxyConfig(string host, int port, string account, string password)
{
this.Host = host;
this.Port = port;
this.Account = account;
this.Password = password;
}
}
DownloadProcess.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;
using System.Text.RegularExpressions;
public class DownloadProcess
{
public static string GetHtmlSource(string url, ProxyConfig proxy)
{
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
// 設置代理伺服器
if (proxy != null)
{
WebProxy p = new WebProxy(proxy.Host, proxy.Port);
p.Credentials = new NetworkCredential(proxy.Account, proxy.Password);
request.Proxy = p;
}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream s = response.GetResponseStream();
StreamReader reader = new StreamReader(s);
string source = reader.ReadToEnd();
reader.Close();
s.Close();
response.Close();
return source;
}
/// <summary>
/// 目標網址
/// </summary>
public string Url { get; set; }
/// <summary>
/// 儲存的目錄位置
/// </summary>
public string StorePath { get; set; }
/// <summary>
/// 儲存的檔名 (Optional)
/// </summary>
public string StoreFilename
{
get { return this._StoreFilename; }
set
{
this._IsFilenameCustomized = true;
this._StoreFilename = value;
}
}
/// <summary>
/// 代理伺服器設定
/// </summary>
public ProxyConfig Proxy { get; set; }
/// <summary>
/// 串流(資料)長度
/// </summary>
public long Length { get; private set; }
/// <summary>
/// 已收到的串流(資料)長度
/// </summary>
public long AcceptedLength { get; private set; }
/// <summary>
/// 開始下載時間
/// </summary>
public DateTime BeginTime { get; private set; }
/// <summary>
/// 完成下載時間
/// </summary>
public DateTime EndTime { get; private set; }
/// <summary>
/// 處理完成
/// </summary>
public bool IsCompleted { get; private set; }
/// <summary>
/// 儲存檔名
/// </summary>
private string _StoreFilename;
/// <summary>
/// 自訂儲存檔名
/// </summary>
private bool _IsFilenameCustomized = false;
/// <summary>
/// 停止下載標記
/// </summary>
private bool _StopFlag = false;
/// <summary>
/// 讀取時的Buffer大小
/// </summary>
private int _ReadBuffer = 128;
/// <summary>
/// 寫入磁碟間隔(sec)
/// </summary>
private int _FlushInterval = 5;
/// <summary>
/// 執行寫入磁碟旗標
/// </summary>
private bool _IsFlushing = false;
/// <summary>
/// 記錄寫入磁碟時間
/// </summary>
private DateTime _LastFlushTime;
public DownloadProcess()
{
this._LastFlushTime = DateTime.Now;
}
public DownloadProcess(string url, string storePath)
: this()
{
this.Url = url;
this.StorePath = storePath;
}
public DownloadProcess(string url, string storePath, ProxyConfig proxy)
: this(url, storePath)
{
this.Proxy = proxy;
}
/// <summary>
/// 開始下載
/// </summary>
public void Start()
{
new Thread(() =>
{
this.AcceptedLength = 0;
this.IsCompleted = false;
this.BeginTime = DateTime.Now;
this.EndTime = DateTime.MinValue;
// 解析檔名
this.ParseFileName();
HttpWebRequest request = WebRequest.Create(this.Url) as HttpWebRequest;
// 設置代理伺服器
if (this.Proxy != null)
{
WebProxy p = new WebProxy(this.Proxy.Host, this.Proxy.Port);
p.Credentials = new NetworkCredential(this.Proxy.Account, this.Proxy.Password);
request.Proxy = p;
}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
// 檢查附件名稱
this.ParseAttachmentName(response);
// 嘗試取得串流長度
this.Length = response.ContentLength;
// 讀取位元數
int readed = 0;
// Buffer
byte[] buf = new byte[this._ReadBuffer];
// 暫存資料
MemoryStream ms = new MemoryStream();
Stream stream = response.GetResponseStream();
while ((readed = stream.Read(buf, 0, buf.Length)) > 0)
{
// 記錄接收的串流長度
this.AcceptedLength += readed;
// 寫入暫存
ms.Write(buf, 0, readed);
// 寫入磁碟
if (!this._IsFlushing && DateTime.Now.AddSeconds(-1 * this._FlushInterval) > this._LastFlushTime)
{
ms.Close();
this.FlushToDisk(ms.ToArray());
ms = new MemoryStream();
}
// 強迫中斷
if (this._StopFlag) break;
}
stream.Close();
ms.Close();
// 等待未完成寫入作業
while (this._IsFlushing)
{
Thread.Sleep(100);
}
this.FlushToDisk(ms.ToArray());
this.EndTime = DateTime.Now;
this.IsCompleted = true;
}).Start();
}
/// <summary>
/// 中斷下載
/// </summary>
public void Stop()
{
this._StopFlag = true;
}
/// <summary>
/// 由輸入網址產生檔名
/// </summary>
private void ParseFileName()
{
if (!this._IsFilenameCustomized && !string.IsNullOrWhiteSpace(Url))
{
Uri url = new Uri(this.Url);
this.StoreFilename = url.Segments[url.Segments.Length - 1];
}
}
/// <summary>
/// 檢查是否有附件名稱
/// </summary>
/// <param name="res"></param>
private void ParseAttachmentName(HttpWebResponse res)
{
if (!string.IsNullOrWhiteSpace(res.Headers["Content-Disposition"]))
{
string filename = Regex.Match(
res.Headers["Content-Disposition"],
"filename=(.+)",
RegexOptions.IgnoreCase
).Groups[1].Value;
if (!string.IsNullOrWhiteSpace(filename))
{
this.StoreFilename = filename;
}
}
}
/// <summary>
/// 將暫存資料寫入磁碟
/// </summary>
/// <param name="buffer"></param>
private void FlushToDisk(byte[] buffer)
{
new Thread(() =>
{
// 標記為寫入中
this._IsFlushing = true;
FileStream fs = new FileStream(
Path.Combine(this.StorePath, this.StoreFilename),
FileMode.Append, FileAccess.Write, FileShare.Write
);
fs.Write(buffer, 0, buffer.Length);
fs.Close();
// 延遲
Thread.Sleep(100);
// 記錄寫入時間
this._LastFlushTime = DateTime.Now;
this._IsFlushing = false;
}).Start();
}
/// <summary>
/// 以適當單位顯示大小
/// </summary>
/// <param name="length">位元數</param>
/// <param name="ext">單位</param>
/// <returns></returns>
private string toSize(double length, SizeExtension ext)
{
if (ext == SizeExtension.Byte && length < 1) return "0 Byte";
if (ext == SizeExtension.GB) return string.Format("{0:00.00} {1}", length, ext);
if (length < 1024)
{
return string.Format("{0:##.##} {1}", length, ext);
}
else
{
return toSize(length / 1024, (SizeExtension)(ext + 1));
}
}
/// <summary>
/// 串流(資料)長度
/// </summary>
/// <returns></returns>
public string GetLength()
{
return this.toSize(this.Length, SizeExtension.Byte);
}
/// <summary>
/// 已收到的串流(資料)長度
/// </summary>
/// <returns></returns>
public string GetAcceptedLenght()
{
return this.toSize(this.AcceptedLength, SizeExtension.Byte);
}
}