之前寫過利用Csharp的WebRequest來下載網頁的內容,這個範例下載的內容是文字內容,如果要下載binary二位元的檔案,就需要修改原本使用的StreamReader變成使用Stream,在之前的範例都有補上內容了,另外還針對deflate及Gzip網頁壓縮功能進行了支援。
這個範例裡使用了Thread來監控下載進度顯示於ProgressBar上。
其中一個Thread負責下載檔案,一個Thread監控目前下載的總byte數/檔案大小,還有一個Thread負責invoke delegate委派的事件來調整ProgressBar數量。
不過這個範例是利用header裡的Content-Length來取得檔案大小的,所以有時直接下載檔案時,主機並不會把Content-Length設定,所以程式就無法執行了,如果是自己的Web Server建議可以自己寫一隻程式來控制,先讀取檔案大小設定Content-Length後,再response出檔案。
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 檔案下載程式”