2012-07-27 114 views
2

這是我的C#代碼從我的服務器下載ZIP文件。當我下載我沒有收到該文件,但它被部分下載。文件沒有完全下載

public static void Download(String strURLFileandPath, String strFileSaveFileandPath) 
{ 
    HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(strURLFileandPath); 
    HttpWebResponse ws = (HttpWebResponse)wr.GetResponse(); 
    Stream str = ws.GetResponseStream(); 
    byte[] inBuf = new byte[100000]; 
    int bytesToRead = (int)inBuf.Length; 
    int bytesRead = 0; 
    while (bytesToRead > 0) 
    { 
     int n = str.Read(inBuf, bytesRead, bytesToRead); 
     if (n == 0) 
      break; 
     bytesRead += n; 
     bytesToRead -= n; 
    } 
    try 
    { 

     FileStream fstr = new FileStream(strFileSaveFileandPath, FileMode.OpenOrCreate, FileAccess.Write); 
     fstr.Write(inBuf, 0, bytesRead); 
     str.Close(); 
     fstr.Close(); 
    } 
    catch (Exception e) { 
     MessageBox.Show(e.Message); 
    } 
} 

我的事情的問題在這裏

byte[] inBuf = new byte[100000]; 

發生當我增加byte[] inBuf = new byte[100000];價值byte[] inBuf = new byte[10000000];

該文件是完全下載。

但我的問題是,如果我下載大於50 MB的文件(例如:200 MB)。

這種方法不好。

誰能告訴我如何解決這個問題?

+1

你的鍵盤似乎有同樣的問題。 :) – leppie 2012-07-27 12:06:47

+0

不要你在他的文件大小,你的下載 – JohnnBlade 2012-07-27 12:09:54

回答

3

您可以使用Stream.CopyTo()方法直接從流複製到流。

甚至更​​簡單:使用WebClient類及其DownloadFile方法下載文件。該解決方案將取代您的完整方法:

var client = new WebClient(); 
client.DownloadFile(strURLFileandPath, strFileSaveFileandPath); 
+0

謝謝重播 頭文件得到響應但爲什麼表單會不響應? – Arun 2012-07-27 14:34:56

+0

這是因爲下載是在與UI相同的線程中執行的。當文件被下載時,UI不能處理任何消息。您應該使用[DownloadFileAsync](http://msdn.microsoft.com/en-us/library/ms144196)方法並將事件處理程序附加到'DownloadFileCompleted'事件,以便知道下載何時完成。請注意,您的下載方法調用將立即返回。任何需要完整本地文件的代碼都必須放在事件處理程序中! – fero 2012-07-27 14:50:05

+0

謝謝你。 我管理與後臺工作的問題 我希望爲此設置一個進度條。是webclient有任何事件的下載進度? 如果不是我如何設置進度條? – Arun 2012-07-27 14:56:48

0

在讀取文件時寫入文件。這樣,在寫入或完成下載之前,您不必將所有字節保留在內存中。

FileStream fstr = new FileStream(strFileSaveFileandPath, FileMode.OpenOrCreate, FileAccess.Write); 
int bytesRead; 
do 
{ 
    bytesRead = str.Read(inBuf, 0, bytesToRead); 
    fstr.Write(inBuf, 0, bytesRead); 
}while (bytesToRead > 0); 

str.Close(); 
fstr.Close(); 
0

由於FERO建議最好使用Stream.CopyTo()

但是,如果你決心做副本流,以手動方式流(或需要知道如何使用流在將來),您絕不應手動指定緩衝區大小。您通常需要使用緩衝區的最大大小沒有重疊,以避免過多的內存消耗,在ResponseSream的情況下,你可以得到ContentLength您的StreamReader

HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(strURLFileandPath); 
HttpWebResponse ws = (HttpWebResponse)wr.GetResponse(); 
Stream str = ws.GetResponseStream(); 
byte[] inBuf = new byte[str.ContentLength]; 
int bytesToRead = (int)inBuf.Length; 

還記得和你Flush()輸出。

+0

,如果文件真的很大,那麼效果不好 – Qnan 2012-07-27 12:11:39

+0

@MikhailKozhevnikov我已經編輯過反思和澄清,這不是最好的soltuion,但只是他的問題的答案。最好的解決方案是避免手動迭代流的copyto方法。 – 2012-07-27 12:15:01