2013-04-17 97 views
2

我正在開發從給定URL下載視頻的應用程序。問題是我沒有收到整個文件內容,然後無法播放該文件。例如,試圖下載大小爲〜2.23 MB的視頻,僅給出我〜2.11 MB的視頻。當我在瀏覽器中使用URL時,會顯示一個對話框來保存視頻,並且文件已成功下載。未完全下載文件

我試過使用WebClient類,它的工作原理,但我想下載文件塊,以便能夠報告狀態(完成百分比)。下面是我使用的代碼:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    int bufferSize = 1024 * 300; 
    string filePath = saveFileDialog.FileName; 
    if (File.Exists(filePath)) 
     File.Delete(filePath); 
    int totalBytes = 0; 
    HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(DownloadUrl); 
    long contentLength = webRequest.GetResponse().ContentLength; 
    using (Stream webStream = webRequest.GetResponse().GetResponseStream()) 
    using (StreamReader reader = new StreamReader(webStream)) 
    using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath))) 
    { 
     do 
     { 
      char[] buffer = new char[bufferSize]; 
      bytesRead = reader.ReadBlock(buffer, 0, bufferSize); // also tried with Read(buffer, 0, bufferSize); 
      totalBytes += bytesRead; 
      Console.WriteLine("Bytes read: " + bytesRead + " Total Bytes: " + totalBytes + " Content length: " + contentLength); 
      if (bytesRead > 0) 
       fileWriter.Write(buffer, 0, bytesRead); 
     } while (!reader.EndOfStream); 
    } 
} 

我也試圖讀取直到bytesRead = 0,但它是同樣的結果。 有什麼,我失蹤?

+0

嘗試在你的作家上調用'.Flush()'。 – MAV

+0

@MAV問題不在寫文件,而是在接收它。接收的字節數小於預期的字節數。 – niculare

回答

1

我建議您使用DownloadFileAsync來代替。這爲您提供了兩個事件,使您可以更輕鬆地跟蹤下載的進度。

DownloadProgressChangedEventHandler

DownloadFileCompleted

一個非常簡單的實現會是這個樣子。

WebClient client = new WebClient(); 

client.DownloadProgressChanged += 
     new DownloadProgressChangedEventHandler(DownloadProgressCallback); 

client.DownloadFileAsync(DownloadUrl, filePath); 

然後有一個函數可以更新你的進度條。

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

您也可以訪問數據,如e.BytesReceivede.TotalBytesToReceive


編輯:

我不得不這樣做主要的變化是你的緩衝區改變從char[]byte[],然後使用流而不是一個StreamReader的。

我們還通過檢查是否有任何字節寫入我們的硬盤來檢查文件的結尾。如果沒有人可以寫,我們知道我們已經完成了。

private static void download() 
{ 
    int bufferSize = 1024 * 300; 
    string filePath = "Test.exe"; 

    if (File.Exists(filePath)) 
     File.Delete(filePath); 
    int totalBytes = 0; 
    HttpWebRequest webRequest = 
     (HttpWebRequest) 
     HttpWebRequest.Create(
      @"http://www.rarlab.com/rar/wrar420.exe"); 
    long contentLength = webRequest.GetResponse().ContentLength; 
    Console.WriteLine(totalBytes); 

    using (WebResponse webResponse = webRequest.GetResponse()) 
    using (Stream reader = webResponse.GetResponseStream()) 
    using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath))) 
    { 
     int bytesRead = 0; 
     byte[] buffer = new byte[bufferSize]; 
     do 
     { 
      bytesRead = reader.Read(buffer, 0, buffer.Length); 
      totalBytes += bytesRead; 
      fileWriter.Write(buffer, 0, bytesRead); 
      Console.WriteLine("BytesRead: " + bytesRead + " -- TotalBytes: " + totalBytes); 

     } while (bytesRead > 0); 
    } 
} 
+0

這將是一個更容易的解決方案,但我想知道爲什麼我的解決方案無法正常工作,儘管它似乎沒問題。 – niculare

+0

@niculare更新了工作答案。 – eandersson

+0

現在我不得不下班回家了,但如果您需要更詳細的解釋,我會在家後進入更多細節。 – eandersson

0

嘗試

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    int bufferSize = 1024 * 300; 
    string filePath = saveFileDialog.FileName; 
    if (File.Exists(filePath)) 
     File.Delete(filePath); 
    int totalBytes = 0; 
    HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(DownloadUrl); 
    long contentLength = webRequest.GetResponse().ContentLength; 
    using (Stream webStream = webRequest.GetResponse().GetResponseStream()) 
    using (StreamReader reader = new StreamReader(webStream)) 
    using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath))) 
    { 
     do 
     { 
      char[] buffer = new char[bufferSize]; 
      bytesRead = reader.ReadBlock(buffer, 0, bufferSize); // also tried with Read(buffer, 0, bufferSize); 
      totalBytes += bytesRead; 
      Console.WriteLine("Bytes read: " + bytesRead + " Total Bytes: " + totalBytes + " Content length: " + contentLength); 
      if (bytesRead > 0) 
       fileWriter.Write(buffer, 0, bytesRead); 
     } while (!reader.EndOfStream); 
     fileWriter.flush(); 
    } 
} 

嗨,那是我不好,我只是說了fileWriter.flush();環外

+2

我會建議你準確地評論你改變了什麼,爲什麼。 – eandersson