2011-06-10 226 views
16

我在這裏是因爲在通過ftp協議下載某些文件時遇到問題。這很奇怪,因爲它偶爾會出現,甚至是同一個文件。底層連接已關閉:接收時出現意外錯誤

只是精度:我下載非常大的文件(500莫30Go)

這裏是那種通過我的函數返回的異常:(抱歉,這是法語)

System.Net.WebException: La connexion sous-jacente a été fermée : Une erreur inattendue s'est produite lors de la réception. à System.Net.FtpWebRequest.CheckError() à System.Net.FtpWebRequest.SyncRequestCallback(Object obj) à System.IO.Stream.Close() à System.Net.ConnectionPool.Destroy(PooledStream pooledStream) à System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse) à System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage) à System.Net.FtpWebRequest.SyncRequestCallback(Object obj) à System.Net.CommandStream.Abort(Exception e) à System.Net.CommandStream.CheckContinuePipeline() à System.Net.FtpDataStream.System.Net.ICloseEx.CloseEx(CloseExState closeState) à System.Net.FtpDataStream.Dispose(Boolean disposing) à System.IO.Stream.Close() à UtilityClasses.FTP.Download(String srcDirectoryPath, String file, String destDirectoryPath)

這裏是用來下載代碼:

的下載方法:

public Dictionary<string, object> Download(string srcDirectoryPath, string file, string destDirectoryPath, int attemptLimitNb, int delay) 
    { 
     int attemptNb = 0; 
     bool downloadFailed; 
     Dictionary<string, object> result = new Dictionary<string,object>(); 

     do 
     { 
      attemptNb++; 
      result = Download(srcDirectoryPath, file, destDirectoryPath); 
      downloadFailed = result["downloadfailed"] != null; 
      if (downloadFailed) Thread.Sleep((int)(1000 * delay)); 
     } 
     while (downloadFailed && attemptNb < attemptLimitNb); 
     return result; 
    } 

public Dictionary<string, object> Download(string srcDirectoryPath, string file, string destDirectoryPath) 
    { 
     Exception downloadFailed = null; 
     Dictionary<string, object> result = new Dictionary<string, object>(); 
     bool fileFound = false; 

     try 
     { 
      if (destDirectoryPath == null || !Directory.Exists(destDirectoryPath)) throw new Exception("Download destination path does not exist"); 
      if (file != null && file != "") 
      { 
       if (file.Contains("/")) 
       { 
        throw new Exception("Invalid file name. Impossible to download"); 
       } 

       Uri serverUri; 
       if (srcDirectoryPath == null || srcDirectoryPath == "") 
       { 
        serverUri = new Uri("ftp://" + this.Server + "/" + file); 
       } 
       else if (Regex.IsMatch(srcDirectoryPath, "^/.*$") || Regex.IsMatch(srcDirectoryPath, "^.*/$")) 
       { 
        throw new Exception("Path must not start and end with '/'"); 
       } 
       else 
       { 
        serverUri = new Uri("ftp://" + this.Server + "/" + srcDirectoryPath + "/" + file); 
       } 

       if (serverUri.Scheme != Uri.UriSchemeFtp) throw new Exception("server URI Scheme does not match FTP URI Scheme"); 

       if (Exists(srcDirectoryPath, file)) 
       { 
        fileFound = true; 

        FtpWebRequest downloadRequest = (FtpWebRequest)FtpWebRequest.Create(serverUri); 
        downloadRequest.Credentials = new NetworkCredential(UserName, Password); 
        downloadRequest.KeepAlive = false; 
        downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile; 
        FtpWebResponse response = (FtpWebResponse)downloadRequest.GetResponse(); 

        Stream responseStream = response.GetResponseStream(); 
        FileStream fileStream = new FileStream(Path.Combine(destDirectoryPath, file), FileMode.Create); 
        byte[] buffer = new byte[2000]; 
        int read = 0; 
        try 
        { 
         do 
         { 
          read = responseStream.Read(buffer, 0, buffer.Length); 
          fileStream.Write(buffer, 0, read); 
          fileStream.Flush(); 
         } 
         while (read != 0); 
        } 
        catch (Exception e) 
        { 
         fileStream.Close(); 
         responseStream.Close(); 
         response.Close(); 
         throw e; 
        } 
        fileStream.Close(); 
        responseStream.Close(); 
        response.Close(); 
       } 
      } 
     } 
     catch (WebException webExcptn) 
     { 
      downloadFailed = webExcptn; 
     } 
     finally 
     { 
      result.Add("filefound", fileFound); 
      result.Add("downloadfailed", downloadFailed); 
     } 

     return result; 
    } 

Exists方法:

public bool Exists(string srcPath, string elementName) 
    { 
     if (elementName == null || elementName == "") 
     { 
      return false; 
     } 

     Uri serverUri; 
     bool res = false; 

     if (srcPath == null || srcPath == "") 
     { 
      serverUri = new Uri("ftp://" + this.Server); 
     } 
     else if (Regex.IsMatch(srcPath, "^/.*$") || Regex.IsMatch(srcPath, "^.*/$")) 
     { 
      throw new Exception("Path must not start and end with '/'"); 
     } 
     else 
     { 
      serverUri = new Uri("ftp://" + this.Server + "/" + srcPath); 

     } 
     if (serverUri.Scheme != Uri.UriSchemeFtp) throw new Exception("server URI Scheme does not match FTP URI Scheme"); 

     FtpWebRequest listingRequest = (FtpWebRequest)FtpWebRequest.Create(serverUri); 
     listingRequest.Credentials = new NetworkCredential(UserName, Password); 
     listingRequest.KeepAlive = false; 
     listingRequest.Method = WebRequestMethods.Ftp.ListDirectory; 
     FtpWebResponse response = (FtpWebResponse)listingRequest.GetResponse(); 

     Stream responseStream = response.GetResponseStream(); 
     StreamReader streamReader = new StreamReader(responseStream); 
     string ftpElementName; 
     do 
     { 
      ftpElementName = Path.GetFileName(streamReader.ReadLine()); 
      if (ftpElementName == null) break; 
      else 
      { 
       string pattern = "^" + elementName.Replace("[", "\\[").Replace("]", "\\]").Replace("+", "[+]").Replace(".", "[.]") + "$"; 
       if (Regex.IsMatch(ftpElementName, pattern, RegexOptions.IgnoreCase)) 
       { 
        res = true; 
       } 
      } 
     } 
     while (ftpElementName != null && !res); 
     streamReader.Close(); 
     responseStream.Close(); 
     response.Close(); 

     return res; 
    } 

也許這是一個超時問題,但我真的不知道。我花了很長時間尋找答案,但沒有成功。也許你們中的一些人會有解決方案。

///

編輯:一些進展:

我過我在調試模式下的代碼與VS而事實上以上的例外是前一個的結果。 (我並不知道,因爲我只寫了最後一個異常的日誌文件中返回)

原來這裏是例外:

Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. 

第二異常是由下載方法這部分代碼引起的:

catch (Exception e) 
{ 
    fileStream.Close(); 
    responseStream.Close(); // <<<<<<<<<<<<<< 
    response.Close(); 
    throw e; 
} 

我一直在我的調查,但似乎「超時PB」假說是最穩定的。今晚我會嘗試一個很大的超時值。

+1

不要道歉。我記得的唯一一部法語是「Je ne parle Francais」和「Je voudrais une kilo du pomme du terre,s'il vous plais」,這兩個都不是很有用,可能是可怕的拼寫:-)你做得更好工作比我在類似的情況下能夠。 – paxdiablo 2011-06-10 09:51:04

+13

你的英語其實很不錯。你已經設法問了一個問題,這個問題比許多訪問這個網站並以英語作爲第一語言的人更好的措辭和更好的結構。 – mdm 2011-06-10 09:52:48

+0

另外,如果您使用常規FTP客戶端連接到網站會發生什麼情況?你可以下載文件嗎?聽起來好像你和服務器之間存在連接錯誤 - 你的代碼看起來不錯。如果你把你的代碼指向另一個FTP站點(也許是你的機器上的本地FTP服務器),那麼怎麼辦?它會失敗嗎? – mdm 2011-06-10 09:55:20

回答

2

這裏的東西一個很好的線程嘗試:

http://social.msdn.microsoft.com/Forums/en/ncl/thread/47634ec2-4d40-4d3f-b075-8cc92bfa2b24

增加超時可能是最少的一個好主意。

+0

我將嘗試此解決方案。 – Hariboox 2011-06-10 10:17:45

+0

我不知道什麼解決了這個問題,但它看起來與你正在經歷的相似。大文件可能會變得複雜。 – ScottE 2011-06-10 10:22:51

+0

我想我現在已經接近解決方案。讓我看看我的新編輯 – Hariboox 2011-06-10 16:38:06

12

只是想加強ScottE的診斷,並且更加具體。超時很可能是問題。

FtpWebRequest的.Net執行錯誤或the MSDN document有錯字,FtpWebRequest.Timeout的默認值不是-1(無限)。它是100000(100秒)。

另外還有另一個超時問題。一些測試顯示responseStream的超時值始終爲300000(300秒)。我不知道這個值是如何分配的。無論如何,這個值需要修改,以適應大型文件。

總之,解決方案是將FtpWebRequest.Timeout和Stream.Timeout設置爲足夠大的值。

+0

我可以確認FtpWebRequest.Timeout文檔是錯誤的。 @洪是正確的...它是100秒。 – 2013-02-12 05:30:22

相關問題