2009-07-03 90 views
19

我需要通過HTTP在C#控制檯應用程序中下載大文件文件(2   GB)。問題是,在大約1.2   GB之後,應用程序內存不足。如何在.NET中下載大文件(通過HTTP)?

下面是我使用的代碼:

WebClient request = new WebClient(); 
request.Credentials = new NetworkCredential(username, password); 
byte[] fileData = request.DownloadData(baseURL + fName); 

正如你所看到的......我直接把文件讀入內存中。我敢肯定,如果我要以塊的形式從HTTP中讀取數據並將其寫入磁盤上的文件,我可以解決這個問題。

我該怎麼做?

回答

9

您需要獲取響應流,然後讀取塊,將每個塊寫入文件以允許重用內存。

正如你所寫,整個響應,所有2GB,都需要在內存中。即使在一個64位系統上,它也會達到單個.NET對象的2GB限制。


更新:更簡單的選項。獲取WebClient爲您完成工作:使用其DownloadFile方法將數據直接放入文件中。

28

WebClient類是簡化場景的類。一旦你通過簡單的場景(你有),你必須回退一點,並使用WebRequest。

使用WebRequest,您將可以訪問響應流,並且您可以遍歷它,讀取一點並寫一點點,直到完成。


例子:

public void MyDownloadFile(Uri url, string outputFilePath) 
{ 
    const int BUFFER_SIZE = 16 * 1024; 
    using (var outputFileStream = File.Create(outputFilePath, BUFFER_SIZE)) 
    { 
     var req = WebRequest.Create(url); 
     using (var response = req.GetResponse()) 
     { 
      using (var responseStream = response.GetResponseStream()) 
      { 
       var buffer = new byte[BUFFER_SIZE]; 
       int bytesRead; 
       do 
       { 
        bytesRead = responseStream.Read(buffer, 0, BUFFER_SIZE); 
        outputFileStream.Write(buffer, 0, bytesRead); 
       } while (bytesRead > 0); 
      } 
     } 
    } 
} 

注意,如果WebClient.DownloadFile工作,那麼我把它叫做最好的解決方案。我在發佈「DownloadFile」答案之前寫了上面的內容。我也是在早上寫的,所以可能需要一點鹽(和測試)。

+0

感謝您的詳細解答和代碼段! 這對於我想在數據到達時處理數據的情況非常有用! – 2009-07-03 13:43:22

+0

這段代碼中的異常處理或重試機制呢?網絡斷開連接等。 – 2013-06-18 07:11:38

2

WebClient.OpenRead返回一個Stream,只是用閱讀來遍歷所有的內容,所以數據不會在內存中緩衝,但可以寫成塊到文件中。