Popular Posts
Enable SSL connection for Jsoup import org.jsoup.Connection; import org.jsoup.Jsoup; import javax.net.ssl.*; import java.io.IOException; import java.security.KeyManagement... Join related table and count rows or sum sql server 2005 count rows: SELECT * FROM Table1 LEFT JOIN     (SELECT Level1ID, COUNT(Level2ID) AS Total FROM Table2 GROUP BY Level1ID) AS... Append soap header into axis When axis generate classese of web service, it won't include the request of soap header. Here is a way to append soap header manually i...
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);
    }
}