2013-05-26 31 views
0

我在寫一個管理遊戲的mods/addons庫的應用程序。每隔一段時間,這些mod中的一個都有更新可用,並且使用WebClient.DownloadFileAsync()下載新版本,通過讀取WebRequest響應中的Content-Disposition來檢索文件名。當異步下載第二個文件時WebClient凍結,如果我從Content-Disposition獲取原始文件名

當兩次或多次更新可用時,第一次下載完全正常,但是當您嘗試下載第二個文件而未重新啓動應用程序時,WebClient會凍結,該文件將使用檢索到的名稱創建,但包含0個字節, DownloadProgressChanged或DownloadFileCompleted事件被觸發。

如果我不嘗試檢索原始文件名,並且只給它們一個本地名稱,則WebClient不會凍結。但我需要原始文件名。

有什麼我可以做的,以避免這個問題,同時仍然能夠檢索原始文件名?

private void Download(string url, string downloadDirectory) 
{ 
    WebClient wc = new WebClient(); 
    string filename = FilenameFromURL(url); 

    wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress); 
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadComplete); 

    wc.DownloadFileAsync(new Uri(url), downloadDirectory + filename); 
} 

private string FilenameFromURL(string url) 
{ 
    return new ContentDisposition(WebRequest.Create(url).GetResponse().Headers["Content-Disposition"].ToString()).FileName; 
} 

private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e) 
{ 
    downloadProgressBar.Value = e.ProgressPercentage; 
} 

private void DownloadComplete(object sender, AsyncCompletedEventArgs e) 
{ 
    // ... 
} 
+0

你確定你沒有吞下異常嗎?你厭倦了一些HTTP調試嗎?舉例來說,小提琴手? –

回答

0

我設法通過Web客戶端是通過該事件處理程序的參數下載文件的實例,然後使用來獲得原始文件名,而不是解決問題使用它的一個單獨的實例來檢索文件名。

貸款this question幫助我找出解決方案。

使用此解決方案,因爲直到下載文件後才能找到原始文件名,我爲其下載臨時名稱並在AsyncCompletedEventHandler中下載完成時重命名它。

private void Download(string url, string downloadDirectory) 
{ 
    WebClient wc = new WebClient(); 

    wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress); 
    wc.DownloadFileCompleted += new AsyncCompletedEventHandler((sender, e) => DownloadComplete(sender, e, wc)); 

    wc.DownloadFileAsync(new Uri(url), downloadDirectory + "temp"); 
} 

private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e) 
{ 
    downloadProgressBar.Value = e.ProgressPercentage; 
} 

private void DownloadComplete(object sender, AsyncCompletedEventArgs e, WebClient wc) 
{ 
    string filename = new ContentDisposition(wc.ResponseHeaders["Content-Disposition"].ToString()).FileName; 
    if (File.Exists(downloadDirectory + "temp")) 
    { 
     if (File.Exists(downloadDirectory + filename)) 
      File.Delete(downloadDirectory + filename); 
     File.Move(downloadDirectory + "temp", downloadDirectory + filename); 
    } 

    // ... 
} 
+0

這比你原來的解決方案要好得多......你的'GetFileNameFromUrl'方法開始從服務器上下載文件,但從來沒有獲取文件內容......昂貴的服務器往返和廢棄的Web請求被丟棄誰知道什麼時候(何時垃圾收集器去獲取它)。爲了進一步改進,可以使用.NET 4.5中的TaskAsync重載和TAP工作流代替「EventHandler」方法。 – TCC

0

其實我複製了你在WPF客戶端中的代碼。我從第一個文件轉載了這個問題。我在本地創建了一個0字節長的文件,但沒有內容。

在我的情況下,我添加的解決方案是設置用戶憑證,之後我可以下載多個文件,並反覆(踩上以前的下載)。

我加入這一行:wc.Credentials = CredentialCache.DefaultCredentials;

private void Download(string url, string downloadDirectory, string fileName) 
{ 
    WebClient wc = new WebClient(); 
    wc.Credentials = CredentialCache.DefaultCredentials; 

    wc.DownloadProgressChanged += DownloadProgress; 
    wc.DownloadFileCompleted += DownloadComplete; 
    wc.DownloadFileAsync(new Uri(url), downloadDirectory + fileName); 
} 
+0

無論是否使用using語句,第二個文件下載都會凍結。 –

+0

處於使用中的物體處理正在尋求麻煩。 –

1

我有同樣的問題。幾小時和幾小時結束後,我發現問題出在一個未經處理的流中。我用它來檢查一個文件存在於web目錄中的天氣。

private bool WebFileExists(string url) 
    { 
     bool exists = true; 

     try 
     { 
      using (WebClient testClient = new WebClient()) 
      { 
       testClient.Credentials = new NetworkCredential(_userName, _password); 
       Stream stream = testClient.OpenRead(url); 
       stream.Dispose(); 
      } 
     } 
     catch 
     { 
      exists = false; 
     } 

     return exists; 
    } 
+0

非常感謝。它真的挽救了另一天尋找解決方案 – Mahyar