1.命名空間 System.IO 裡面有個 Class 叫做 WebClient,它提供了一些下載遠端檔案的方法。
2.其中 DownloadFileAsync 和 DownloadDataAsync 二個方法是非同步的,它會在作業期間以事件 DownloadProgressChanged() 傳回下載進度,也會在完成時用事件 DownloadDataCompleted 或 DownloadFileCompleted() 通知呼叫端取回下載結果。
3.基本用法很簡單,程式碼只要幾行就可以了:
貼文包含五個部分,分別是:
(一)使用 System.Net.WebClient 類別中現成的方法。
(二)從 FTP 下載時如何先得到 File Size。
(三)使用 Socket 直接和 FTP Server 建立連線下載檔案。
(四)讓自製的下載方法也能做到非同步(ASYNC)。
(五)整合全部功能並封裝成控制項。
首先要分享的實作經驗是:
- 命名空間 System.IO 裡面有個 Class 叫做 WebClient,它提供了一些下載遠端檔案的方法。
- 其中 DownloadFileAsync 和 DownloadDataAsync 二個方法是非同步的,它會在作業期間以事件 DownloadProgressChanged() 傳回下載進度,也會在完成時用事件 DownloadDataCompleted 或 DownloadFileCompleted() 通知呼叫端取回下載結果。
-
基本用法很簡單,程式碼只要幾行就可以了:
Imports System.Net Imports System.IO Public Class Form1 Private WithEvents 檔案下載器 As New System.Net.WebClient '---下載並存檔--- Private Sub DownLoadFile() Handles btn_DownLoadFile.Click 檔案下載器.DownloadFileAsync(New Uri(TextBox1.Text), TextBox2.Text) End Sub '---下載 File 完成--- Private Sub DownloadFileCompleted(sender As Object, e As System.ComponentModel.AsyncCompletedEventArgs) Handles 檔案下載器.DownloadFileCompleted 檔案下載器.Dispose() If e.Cancelled Then MsgBox("使用者中斷了下載作業!") : Exit Sub If Not IsNothing(e.Error) Then MsgBox("下載失敗!") : Exit Sub MsgBox("下載成功。") End Sub '---當下載 Progress 改變--- Private Sub P1(sender As Object, e As System.Net.DownloadProgressChangedEventArgs) Handles 檔案下載器.DownloadProgressChanged Me.Text = (e.BytesReceived & " -- " & e.ProgressPercentage & "%") End Sub '---使用者放棄鍵--- Private Sub btn_Canel_Click(sender As System.Object, e As System.EventArgs) Handles btn_Canel.Click 檔案下載器.CancelAsync() End Sub End Class
-
執行效果如圖,當下載 Uri 為 HTTP 協定時都還正常(圖1)。
- 而在對象是 FTP 時,下載過程中的 ProgressChange() 事件却只傳回已收到資料的大小(e.BytesReceived)而表示百分比的 e.ProgressPercentage 則傳回了0。
- 另外在 e.TotalBytesToReceive 傳回的是 -1,缺少了百分比的數據,又沒有總長度,自然就不適合使用 ProgressBar 做顯示進度的介面了。
-
MSDN 了一下,發現以下訊息:
這個方法會下載 address 參數中指定之 URI 處的資源。當下載順利完成之後,下載的檔案在本機電腦上會命名為 fileName。
檔案是使用從執行緒集區自動配置的執行緒資源,以非同步方式下載。若要在可以使用檔案時接收通知,請將事件處理常式加入至 DownloadFileCompleted 事件。
這個方法不會在下載資源時封鎖呼叫執行緒。若要在等待下載完成時加以封鎖,請使用其中一個 DownloadFile 方法。
您可以使用 CancelAsync 方法取消尚未完成的非同步作業。
如果 BaseAddress 屬性不是空字串 (""),而且 address 未指定絕對 URI,address 就必須是相對的 URI,並與 BaseAddress 組合形成所要求資料的絕對 URI。
如果 QueryString 屬性不是空字串,它會附加至 address。
這個方法會使用 RETR 命令下載 FTP 資源。對於 HTTP 資源,則會使用 GET 方法。
- 這段文字提到在 FTP 情形下是用 RETR 命令下載檔案,並沒說先用 SIZE 命令查詢一下檔案的大小,所以..關鍵可能就在這兒了
- 而 HTTP 情形下因為有 Header 資料可夾帶屬性去和 Server 交換訊息,就可以用 Content Length 這個屬性取回檔案長度
- 所以,如果在啟動下載之前先查看連線另一端是否為 FTP 服務,若是,就先想辦法取得檔案長度,然後才開始下載,這樣 ProgressBar 就會正常了。
至於如何取得 FTP Server 上面檔案的長度,下回再貼了。
專案原始碼下載:非同步下載_01_demo.rar