Csharp 檔案下載程式

之前寫過利用Csharp的WebRequest來下載網頁的內容,這個範例下載的內容是文字內容,如果要下載binary二位元的檔案,就需要修改原本使用的StreamReader變成使用Stream,在之前的範例都有補上內容了,另外還針對deflate及Gzip網頁壓縮功能進行了支援。

這個範例裡使用了Thread來監控下載進度顯示於ProgressBar上。

CsharpProgressBar1

其中一個Thread負責下載檔案,一個Thread監控目前下載的總byte數/檔案大小,還有一個Thread負責invoke delegate委派的事件來調整ProgressBar數量。

CsharpProgressBar2

不過這個範例是利用header裡的Content-Length來取得檔案大小的,所以有時直接下載檔案時,主機並不會把Content-Length設定,所以程式就無法執行了,如果是自己的Web Server建議可以自己寫一隻程式來控制,先讀取檔案大小設定Content-Length後,再response出檔案。

CsharpProgressBar3

WebModule下載部份

        private decimal bytesProcessed = 0;
        private decimal bytesTotal = 0;
        public decimal getByteTotal()
        {
            return bytesTotal;
        }
        public decimal ByteProcess()
        {
            return bytesProcessed;
        }

        public decimal DownloadFile(string sUrl, string data, string referer, String localFilename)
        {
            // Function will return the number of bytes processed
            // to the caller. Initialize to 0 here.
            bytesProcessed = 0;
            bytesTotal = 0;

            // Assign values to these objects here so that they can
            // be referenced in the finally block
            Stream remoteStream = null;
            Stream localStream = null;
            WebResponse response = null;

            // Use a try/catch/finally block as both the WebRequest and Stream
            HttpWebRequest URLConn = null;
            try
            {
                // sUrl = sUrl.IndexOf(Prop.getProp()["server"]) > -1 ? sUrl : (Prop.getProp()["server"] + sUrl);
                Console.WriteLine(sUrl);
                //URL連線
                URLConn = (HttpWebRequest)WebRequest.Create(sUrl);
                //連線最大等待時間
                URLConn.Timeout = 60000;
                URLConn.Method = "POST";
                //設定Header模擬瀏覽器
                URLConn.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-TW; rv:1.9.1.2) "
                          + "Gecko/20090729 Firefox/3.5.2 GTB5 (.NET CLR 3.5.30729)";
                URLConn.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";

                URLConn.Headers.Set("Accept-Language",
                    "zh-tw,en-us;q=0.7,en;q=0.3");
                URLConn.Headers.Set("Accept-Charse",
                    "Big5,utf-8;q=0.7,*;q=0.7");
                URLConn.Headers["Accept-Encoding"] = "gzip, deflate";
                //設定referer
                if (referer != null)
                {

                    URLConn.Referer = referer;
                }
                //純文字傳送,使用application/x-www-form-urlencoded
                //如需傳送檔案,則需用multipart/form-data
                URLConn.ContentType = "application/x-www-form-urlencoded";
                //自動從導
                URLConn.AllowAutoRedirect = true;

                if (data == null)
                    data = "";
                Console.WriteLine(data);
                //把要傳送的資料變成binary
                byte[] bytes = Encoding.UTF8.GetBytes(data);
                URLConn.ContentLength = bytes.Length;

                //設定Cookie,Session
                URLConn.CookieContainer = cookie;

                //送出post資料
                if (data.Length > 0)
                {
                    Stream oStreamOut = URLConn.GetRequestStream();
                    oStreamOut.Write(bytes, 0, bytes.Length);
                    //oStreamOut.Close();
                }
                string sResponseHeader = URLConn.GetResponse().Headers["Content-Length"];
                bytesTotal = Convert.ToInt32(sResponseHeader);
                response = URLConn.GetResponse();

                if (response != null)
                {
                    // Once the WebResponse object has been retrieved,
                    // get the stream object associated with the response's data
                    remoteStream = response.GetResponseStream();

                    // Create the local file
                    localStream = File.Create(localFilename);

                    // Allocate a 1k buffer
                    byte[] buffer = new byte[1024];
                    int bytesRead;

                    // Simple do/while loop to read from stream until
                    // no bytes are returned
                    Object o = new Object();
                    do
                    {
                        // Read data (up to 1k) from the stream
                        
                            bytesRead = remoteStream.Read(buffer, 0, buffer.Length);

                            // Write the data to the local file
                            localStream.Write(buffer, 0, bytesRead);
                            //Console.WriteLine(bytesProcessed + "\t" + bytesTotal);
                            // Increment total bytes processed
                            //Console.WriteLine(bytesProcessed);
                            bytesProcessed += bytesRead;
                        
                    } while (bytesRead > 0);
                    //bytesProcessed = bytesTotal;
                }

            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                // Close the response and streams objects here 
                // to make sure they're closed even if an exception
                // is thrown at some point
                if (response != null) response.Close();
                if (remoteStream != null) remoteStream.Close();
                if (localStream != null) localStream.Close();
            }

            // Return total bytes processed to caller.
            return bytesProcessed;
        }

Manager 檔案下載Manager主程式

using System;
using System.Windows.Forms;
using System.Threading;



namespace DownLoadManagerTest
{
    public partial class Manager : Form
    {
       
       
       
        public Manager()
        {
            InitializeComponent();
           
        }

        private bool dlsuccess = false;
        private void go()
        {
            bool f = true;
            while (f)
            {
                if (web == null)
                {
                    web = new WebModule();
                    Thread t = new Thread(() => web.DownloadFile(textBox1.Text , "", null,textBox2.Text ));
                    t.Start();

                }
                ThreadStart ts = new ThreadStart(myUI);
                Thread th = new Thread(ts);
                th.Start();

                if (web.getByteTotal() != 0 && web.ByteProcess() >= web.getByteTotal())
                {
                    dlsuccess = true;
                    f = false;
                }

                Thread.Sleep(1000);
            }
           
            Thread cts = new Thread(() => myClose(dlsuccess));
            cts.Start();


        }
        
        private WebModule web = null;
        //delegate委派
        private delegate void myUICallBack();
        private void myUI( )
        {

            if (this.InvokeRequired)
            {
                myUICallBack myUpdate = new myUICallBack(myUI);
                this.Invoke(myUpdate);
            }

            else
            {

                
                    if (web.getByteTotal() != 0)
                    {
                        Console.WriteLine (web.ByteProcess() + "--\t" + web.getByteTotal() + "--\t" + ((web.ByteProcess() / web.getByteTotal())));
                        progressBar.Value = (Int32)((web.ByteProcess() / web.getByteTotal()) * 100);

                    }

            }

        }


        private string msg = "下載失敗!";
        private delegate void myCloseCallBack(Boolean f);
        private void myClose(Boolean f)
         {

             if (this.InvokeRequired)
             {
                 myCloseCallBack myUpdate = new myCloseCallBack(myClose);
                 this.Invoke(myUpdate,f);
             }

             else
             {
                 if(f)
                 {
                     MessageBox.Show(this, "程序執行完成!");
                 }
                 else
                 {
                     MessageBox.Show(this, msg);
                 }
                 Close();
                 Dispose();
             }
         }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            Thread th = new Thread(() => go());
            th.Start();
        }

    }
}

Source原始碼下載

本機下載

One thought to “Csharp 檔案下載程式”

發表迴響