2011-11-08 112 views
0

我想在方法中下載文件,然後使用第一種方法中存儲在變量中的一些數據繼續使用該文件。 我知道你可以使用DownloadFileAsync,但是我需要在DownloadFileCompleted方法中繼續我的工作,並且不能從那裏訪問變量(除非我聲明瞭一些全局變量並使用它,儘管這不是正確的方法我想)。使用進度條下載文件

因此,我使用Google搜索並找到了另一種方式,通過手動下載文件,一點一點地進行。這對我來說很合適。儘管我想知道的是,如果還有其他方法/解決方案對我的問題更簡單?

或者,如果你可以用事件玩耍和實現的東西,對我更合適:)

哦,請更改我的問題,如果你找到一個更好的標題,我想不出一個的。

+0

你的意思是「變量無法從那裏」?與DownloadFileCompleted你可以完全達到一個全局變量 –

+0

@mekici我說,**除非**我宣佈一些全球性的。 – fgblomqvist

+0

ahh ok :)我建議你下載文件異步,也許你可以創建一個類和全局列表然後你可以創建對象並在DownloadFileCompleted方法中添加該列表 –

回答

3

你必須一塊一塊地更新進度條。這段代碼有訣竅。

public class WebDownloader 
{ 
    private static readonly ILog log = LogManager.GetLogger(typeof(WebDownloader)); 

    public delegate void DownloadProgressDelegate(int percProgress); 

public static void Download(string uri, string localPath, DownloadProgressDelegate progressDelegate) 
    { 
     long remoteSize; 
     string fullLocalPath; // Full local path including file name if only directory was provided. 

     log.InfoFormat("Attempting to download file (Uri={0}, LocalPath={1})", uri, localPath); 

     try 
     { 
      /// Get the name of the remote file. 
      Uri remoteUri = new Uri(uri); 
      string fileName = Path.GetFileName(remoteUri.LocalPath); 

      if (Path.GetFileName(localPath).Length == 0) 
       fullLocalPath = Path.Combine(localPath, fileName); 
      else 
       fullLocalPath = localPath; 

      /// Have to get size of remote object through the webrequest as not available on remote files, 
      /// although it does work on local files. 
      using (WebResponse response = WebRequest.Create(uri).GetResponse()) 
      using (Stream stream = response.GetResponseStream()) 
       remoteSize = response.ContentLength; 

      log.InfoFormat("Downloading file (Uri={0}, Size={1}, FullLocalPath={2}).", 
       uri, remoteSize, fullLocalPath); 
     } 
     catch (Exception ex) 
     { 
      throw new ApplicationException(string.Format("Error connecting to URI (Exception={0})", ex.Message), ex); 
     } 

     int bytesRead = 0, bytesReadTotal = 0; 

     try 
     { 
      using (WebClient client = new WebClient()) 
      using (Stream streamRemote = client.OpenRead(new Uri(uri))) 
      using (Stream streamLocal = new FileStream(fullLocalPath, FileMode.Create, FileAccess.Write, FileShare.None)) 
      { 
       byte[] byteBuffer = new byte[1024 * 1024 * 2]; // 2 meg buffer although in testing only got to 10k max usage. 
       int perc = 0; 
       while ((bytesRead = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0) 
       { 
        bytesReadTotal += bytesRead; 
        streamLocal.Write(byteBuffer, 0, bytesRead); 
        int newPerc = (int)((double)bytesReadTotal/(double)remoteSize * 100); 
        if (newPerc > perc) 
        { 
         log.InfoFormat("...Downloading (BytesRead={0}, Perc={1})...", bytesReadTotal, perc); 
         perc = newPerc; 
         if (progressDelegate != null) 
          progressDelegate(perc); 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new ApplicationException(string.Format("Error downloading file (Exception={0})", ex.Message), ex); 
     } 

     log.InfoFormat("File successfully downloaded (Uri={0}, BytesDownloaded={1}/{2}, FullLocalPath={3}).", 
      uri, bytesReadTotal, remoteSize, fullLocalPath); 
    } 
} 

您將需要分離一個線程來運行此代碼,因爲它顯然是同步的。

例如

Task.Factory.StartNew(_ => Download(...)); 
+0

+1爲自我解釋代碼,沒有針頭段落與格式文本。 – pjvds

+0

謝謝你的偉大代碼! 我已經通過它瞭解了一些東西;) – fgblomqvist

+0

很高興它是有用的。我寫了很久以前,現在我正在重寫它,我可能會使用Reactive Extensions來做不同的事情。關於爲什麼我使用webrequest來獲取文件大小的評論有點不清楚 - 我這樣做是因爲其他獲取文件大小的方法在各種情況下都不起作用。 – DanH