Popular Posts
javax.net.ssl.SSLHandshakeException: Connection closed by peer in Android 5.0 Lollipop Recently, there is a error occurs when access website via ssl connection like below although it worked fine several days ago. // Enable SSL... Close window without confirm (I.E only) window.opener=null; window.open('','_self'); window.close(); focus on validating function focusOnInvalidControl() {     for (var i = 0; i < Page_Validators.length; i++) {         if (!Page_Validators[i].isvalid) {     ...
Blog Archive
Stats
DownloadProcess
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);
    }
}