2017-08-30 116 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 '列表' 命令,并解析权限和目录的指标。

相关问题