2010-02-15 79 views
6

我需要處理它之前以編程方式下載大文件。什麼是最好的方式來做到這一點?由於文件很大,我想要特定的時間等待,以便我可以強制退出。如何以編程方式下載大文件在C#中

我知道WebClient.DownloadFile的()。但似乎沒有辦法確定等待時間來強制退出。

try 
{ 
    WebClient client = new WebClient(); 
    Uri uri = new Uri(inputFileUrl); 
    client.DownloadFile(uri, outputFile); 
} 
catch (Exception ex) 
{ 
    throw; 
} 

的另一種方法是使用命令行實用程序(wget的)要下載的文件,並觸發使用的ProcessStartInfo和使用過程WaitForExit命令(INT毫秒)強行退出。

ProcessStartInfo startInfo = new ProcessStartInfo(); 
//set startInfo object 

try 
{ 
    using (Process exeProcess = Process.Start(startInfo)) 
    { 
     //wait for time specified 
     exeProcess.WaitForExit(1000 * 60 * 60);//wait till 1m 

     //check if process has exited 
     if (!exeProcess.HasExited) 
     { 
      //kill process and throw ex 
      exeProcess.Kill(); 
      throw new ApplicationException("Downloading timed out"); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    throw; 
} 

有沒有更好的方法?請幫忙。謝謝。

+0

什麼是URI ?這是FTP嗎? – t0mm13b 2010-02-15 23:20:27

回答

16

使用WebRequest,並獲得response stream。然後從響應Stream字節塊中讀取,並將每個塊寫入目標文件。這樣,您就可以控制何時停止,如果下載需要太長時間,因爲你得到的塊之間的控制,你可以決定是否下載已經基於時鐘超時:           

 DateTime startTime = DateTime.UtcNow; 
     WebRequest request = WebRequest.Create("http://www.example.com/largefile"); 
     WebResponse response = request.GetResponse(); 
     using (Stream responseStream = response.GetResponseStream()) { 
      using (Stream fileStream = File.OpenWrite(@"c:\temp\largefile")) { 
       byte[] buffer = new byte[4096]; 
       int bytesRead = responseStream.Read(buffer, 0, 4096); 
       while (bytesRead > 0) {  
        fileStream.Write(buffer, 0, bytesRead); 
        DateTime nowTime = DateTime.UtcNow; 
        if ((nowTime - startTime).TotalMinutes > 5) { 
         throw new ApplicationException(
          "Download timed out"); 
        } 
        bytesRead = responseStream.Read(buffer, 0, 4096); 
       } 
      } 
     } 
+0

@orip,它是如何複雜? – juan 2010-02-16 00:07:17

+0

@Juan,對於一個它是同步的。這個例子的異步版本看起來非常不同。但它也拋出了非常用戶友好的WebClient外觀,90%的時間隱藏了很大程度上不相關的流管理內容。 – Josh 2010-02-16 00:15:10

+1

orip,你的代碼要簡單得多。使用Remus代碼的一個優點是我可以下載多少文件。 – hIpPy 2010-02-16 19:59:20

7

如何關於在WebClient類中使用DownloadFileAsync。大約走這條路很酷的事情是,你可以通過調用CancelAsync如果時間太長取消操作。基本上,調用這個方法,如果經過了指定的時間,調用Cancel。

4

這裏問:C#: Downloading a URL with timeout

簡單的解決方案:

public string GetRequest(Uri uri, int timeoutMilliseconds) 
{ 
    var request = System.Net.WebRequest.Create(uri); 
    request.Timeout = timeoutMilliseconds; 
    using (var response = request.GetResponse()) 
    using (var stream = response.GetResponseStream()) 
    using (var reader = new System.IO.StreamReader(stream)) 
    { 
     return reader.ReadToEnd(); 
    } 
} 

更好(更靈活)的解決方案是this answer對同一問題,在WebClientWithTimeout輔助類的形式。

+4

webrequest.timeout只測量直到收到HTTP響應頭的時間,而不是直到響應正文被下載的總時間。 IE瀏覽器。它會影響GetResponse返回之前的時間。 – 2010-02-16 00:08:58

+0

好點,我沒有意識到這一點 – orip 2010-02-16 00:29:16

2

您可以使用DownloadFileAsync作爲@BFree說,然後嘗試用下面的Web客戶端的事件

protected virtual void OnDownloadProgressChanged(DownloadProgressChangedEventArgs e); 
protected virtual void OnDownloadFileCompleted(AsyncCompletedEventArgs e); 

然後你就可以知道進度百分比

e.ProgressPercentage 

希望這有助於

相關問題