2009-07-03 92 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,只是用阅读来遍历所有的内容,所以数据不会在内存中缓冲,但可以写成块到文件中。