2017年9月30日 星期六

C# : 網路下載檔案之下載進度委派 delegate 方法

現在,讓我們來使用委派方法的功能,在這個練習中,我們將會設計一個類別,他會下載一個網路 PDF 檔案,當在下載的過程之中,會將下載檔案的實際讀取到的檔案完成百分比,透過委派方法回報;這個委派方法扮演著一個類似事件,也就是可以接收到處理工作當時狀態的通知,所以,訂閱這個委派事件的用戶端,就可以即時下載進度顯示在螢幕上,讓使用者明瞭這個長時間的工作,現在處理到甚麼進度了。
在這個類別 DownloadFile,我們定義了一個 Download 函式,他使用了 HttpClient.GetAsync 方法,抓取指定 URL 的內容,並且使用 HTTP Header 的 Content-Length 得到要下載的檔案總大小,接著,取得 HttpResponseMessage 之後,使用 HttpResponseMessage.Content.ReadAsStreamAsync() 方法,取得 Stream 行別的物件,便可以開始每次讀取 5120 bytes 大小的內容到程式中。每次完成讀取 5120 bytes,就會呼叫委派方法 onProgress,將處理進度回報,而這個 onProgress 是個委派型別的變數 public delegate void ProgressDelegate(int percent);
    public class DownloadFile
    {
        public delegate void ProgressDelegate(int percent);
        public ProgressDelegate OnProgress;
        public string Url { get; set; } = "http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/js_api_reference.pdf";
        public async void Download()
        {
            var task = Task.Factory.StartNew(async () =>
              {
                  int offset = 5120;
                  int percent = 0;
                  int currentDonload = 0;
                  int getBytes;
                  int lastPercent = -1;
                  using (var client = new HttpClient())
                  {
                      using (var response = await client.GetAsync(Url))
                      {
                          var total = int.Parse(response.Content.Headers.First(h => h.Key.Equals("Content-Length")).Value.First());
                          byte[] content = new byte[total];
                          using (var stream = await response.Content.ReadAsStreamAsync())
                          {
                              var onProgress = OnProgress;
                              while ((getBytes = stream.Read(content, currentDonload, offset)) > 0)
                              {
                                  currentDonload += getBytes;
                                  percent = (int)((1.0*currentDonload / total) * 100);
                                  if (lastPercent != percent)
                                  {
                                      if (onProgress != null)
                                      {
                                          onProgress(percent);
                                      }
                                      lastPercent = percent;
                                  }
                              }
                          }
                      }
                  }
              });
        }
    }
在進行測試的時候,我們建立了這個類別 (DownloadFile) 物件,接者設定 OnProgress 委派欄位,使其綁定到 DownloadStatus 方法上;這個方法就會將現在的處理進度,即時顯示在螢幕上,讓使用者知道現在的處理最新情況。
static void Main(string[] args)
{
    DownloadFile downloadFile = new DownloadFile();
    downloadFile.OnProgress += DownloadStatus;
    Console.WriteLine($"開始進行非同步檔案檔案下載");
    downloadFile.Download();
    Console.WriteLine($"Press any key to Exist...{Environment.NewLine}");
    Console.ReadKey();
}

private static void DownloadStatus(int percent)
{
    if(percent%10==0)
    {
        Console.Write($" {percent}% ");
    }
    else
    {
        Console.Write($".");
    }
}
底下是執行結果
開始進行非同步檔案檔案下載
Press any key to Exist...

 0% ......... 10% ......... 20% ......... 30% ......... 40% ......... 50% ......... 60% ......... 70%

沒有留言:

張貼留言