2017-08-30 134 views
1

,我讀了FTP文件/文件夾列表。檢查是否是文件或文件夾上的FTP

問題是,我不知道,如果是文件或文件夾。 目前我正在檢查字符串是否有擴展名。如果是,則是文件,否則爲文件夾。但是,這還不夠好,它可以存在的文件沒有擴展名和文件夾的擴展名(例如,文件夾名稱可能是FolderName.TXT。)

這是代碼,我用它來列出文件夾的內容:

public async Task<CollectionResult<string>> ListFolder(string path) 
{ 
    try 
    { 
     FtpWebRequest ftpRequest = null; 
     var fileNames = new List<string>(); 
     var res = new CollectionResult<string>(); 
     ftpRequest = ftpBuilder.Create(path, WebRequestMethods.Ftp.ListDirectory); 
     using (var ftpResponse = (FtpWebResponse)await ftpRequest.GetResponseAsync()) 
     using (var ftpStream = ftpResponse.GetResponseStream()) 
     using (var streamReader = new StreamReader(ftpStream, Encoding.UTF8)) 
     { 
      string fileName = streamReader.ReadLine(); 
      while (!string.IsNullOrEmpty(fileName)) 
      { 
       fileNames.Add(Path.Combine(path, fileName.Substring(fileName.IndexOf('/') + 1, fileName.Length - fileName.IndexOf('/') - 1))); 
       fileName = streamReader.ReadLine(); 
      } 
     } 
     ftpRequest = null; 
     res.ListResult = fileNames; 
     return res; 
    } 
    catch (Exception e) 
    { 
     e.AddExceptionParameter(this, nameof(path), path); 
     throw; 
    } 
} 

如果我能夠在while循環中檢測到文件或文件夾是最好的,但是不可能僅從字符串中進行此操作。

謝謝你的幫助。


編輯

我發現類似的問題。 C# FTP, how to check if a Path is a File or a Directory? 但問題是很老,也沒有很好的解決方案。


編輯:解

public async Task<CollectionResult<Tuple<string, bool>>> ListFolder(string path) 
     { 
      try 
      { 
       FtpWebRequest ftpRequest = null; 
       var fileNames = new CollectionResult<Tuple<string, bool>>(); 
       fileNames.ListResult = new List<Tuple<string, bool>>(); 
       if (!(IsFtpDirectoryExist(path))) 
       { 
        throw new RemoteManagerWarningException(ErrorKey.LIST_DIRECTORY_ERROR, fileNames.ErrorMessage = $"path folder {path} not exists"); 
       } 
       ftpRequest = ftpBuilder.Create(path, WebRequestMethods.Ftp.ListDirectoryDetails); 
       using (var ftpResponse = (FtpWebResponse)await ftpRequest.GetResponseAsync()) 
       using (var ftpStream = ftpResponse.GetResponseStream()) 
       using (var streamReader = new StreamReader(ftpStream, Encoding.UTF8)) 
       { 
        while (!streamReader.EndOfStream) 
        { 
         string line = streamReader.ReadLine(); 
         string[] tokens = line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries); 
         // is number: 
         Regex rgx = new Regex(@"^[\d\.]+$"); 
         var isExternalFtpOrUnixDirectoryStyle = !(rgx.IsMatch(line[0].ToString())); 
         string name = string.Empty; 
         bool isFolder = false; 

         if (isExternalFtpOrUnixDirectoryStyle) 
         { 
          name = tokens[8]; 
          var permissions = tokens[0]; 
          isFolder = permissions[0] == 'd'; 
         } 
         else 
         { 
          tokens = line.Split(new[] { ' ' }, 4, StringSplitOptions.RemoveEmptyEntries); 
          name = tokens[3]; 
          isFolder = tokens[2] == "<DIR>"; 
         } 
         name = Path.Combine(path, name); 
         Tuple<string, bool> tuple = new Tuple<string, bool>(name, isFolder); 
         fileNames.ListResult.Add(tuple);       
        } 
       } 
       ftpRequest = null; 
       return fileNames; 
      } 
      catch (Exception e) 
      { 
       e.AddExceptionParameter(this, nameof(path), path); 
       throw; 
      } 
     } 

回答

2

有沒有辦法來確定是否一個目錄條目是一個可移植的方式文件的子目錄與FtpWebRequest或任何其他內置.NET框架的功能。該FtpWebRequest遺憾的是不支持MLSD命令,這是檢索目錄列表中的FTP協議與文件屬性的唯一可移植的方法。另請參閱Checking if object on FTP server is file or directory

的選項有:

  • 上那是一定要失敗的文件,併成功爲目錄(反之亦然)的文件名再做一次手術。即你可以嘗試下載「名稱」。如果成功,它就是一個文件,如果失敗了,它就是一個目錄。
  • 你可能是幸運的,在特定情況下,可以通過文件名告訴從目錄中的文件(即所有文件的擴展名,而子目錄不)
  • 您使用長的目錄列表( LIST命令= ListDirectoryDetails方法),並且嘗試解析一個特定於服務器的列表。許多FTP服務器使用* nix風格的列表,其中您在條目的最開始處用d標識了一個目錄。但是許多服務器使用不同的格式。

    爲了實現解析的一些示例,請參閱:
    * nix的格式:Parsing FtpWebRequest ListDirectoryDetails line
    DOS/Windows格式:C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response


如果你想避免與解析服務器 - 煩惱特定的目錄列表格式,請使用支持MLSD命令和/或解析各種LIST列表格式的第三方庫;和遞歸下載。

例如與WinSCP .NET assembly您可以使用Sesssion.ListDirectory

// Setup session options 
SessionOptions sessionOptions = new SessionOptions 
{ 
    Protocol = Protocol.Ftp, 
    HostName = "example.com", 
    UserName = "user", 
    Password = "mypassword", 
}; 

using (Session session = new Session()) 
{ 
    // Connect 
    session.Open(sessionOptions); 

    RemoteDirectoryInfo directory = session.ListDirectory("/home/martin/public_html"); 

    foreach (RemoteFileInfo fileInfo in directory.Files) 
    { 
     if (fileInfo.IsDirectory) 
     { 
      // directory 
     } 
     else 
     { 
      // file 
     } 
    } 
} 

內部,WinSCP賦予使用MLSD命令,如果服務器支持。如果不是,則使用LIST命令並支持數十種不同的列表格式。

(我是WinSCP的作者)

1

使用FTP '列表' 命令,並解析權限和目錄的指標。

相關問題