【问题标题】:How to check if file exists on FTP before FtpWebRequest如何在 FtpWebRequest 之前检查 FTP 上是否存在文件
【发布时间】:2010-09-25 18:18:03
【问题描述】:

我需要使用FtpWebRequest 将文件放入 FTP 目录。在上传之前,我首先想知道这个文件是否存在。

我应该使用什么方法或属性来检查这个文件是否存在?

【问题讨论】:

    标签: c# .net ftp ftpwebrequest


    【解决方案1】:

    您可以使用WebRequestMethods.Ftp.ListDirectory 来检查文件是否存在,不需要讨厌的try catch 机制。

        private static bool ExistFile(string remoteAddress)
        {
            int pos = remoteAddress.LastIndexOf('/');
            string dirPath = remoteAddress.Substring(0, pos); // skip the filename only get the directory
    
            NetworkCredential credentials = new NetworkCredential(FtpUser, FtpPass);
            FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(dirPath);
            listRequest.Method = WebRequestMethods.Ftp.ListDirectory;
            listRequest.Credentials = credentials;
            using (FtpWebResponse listResponse = (FtpWebResponse)listRequest.GetResponse())
            using (Stream listStream = listResponse.GetResponseStream())
            using (StreamReader listReader = new StreamReader(listStream))
            {
                string fileToTest = Path.GetFileName(remoteAddress);
                while (!listReader.EndOfStream)
                {
                    string fileName = listReader.ReadLine();
                    fileName = Path.GetFileName(fileName);
                    if (fileToTest == fileName)
                    {
                        return true;
                    }
    
                }
            }
            return false;
        }
    
        static void Main(string[] args)
        {
            bool existFile = ExistFile("ftp://123.456.789.12/test/config.json");
        }
    

    【讨论】:

      【解决方案2】:

      FtpWebRequest(也不是 .NET 中的任何其他类)没有任何明确的方法来检查 FTP 服务器上的文件是否存在。您需要滥用 GetFileSizeGetDateTimestamp 之类的请求。

      string url = "ftp://ftp.example.com/remote/path/file.txt";
      
      WebRequest request = WebRequest.Create(url);
      request.Credentials = new NetworkCredential("username", "password");
      request.Method = WebRequestMethods.Ftp.GetFileSize;
      try
      {
          request.GetResponse();
          Console.WriteLine("Exists");
      }
      catch (WebException e)
      {
          FtpWebResponse response = (FtpWebResponse)e.Response;
          if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
          {
              Console.WriteLine("Does not exist");
          }
          else
          {
              Console.WriteLine("Error: " + e.Message);
          }
      }
      

      如果您想要更直接的代码,请使用一些第 3 方 FTP 库。

      例如WinSCP .NET assembly,你可以使用它的Session.FileExists method

      SessionOptions sessionOptions = new SessionOptions {
          Protocol = Protocol.Ftp,
          HostName = "ftp.example.com",
          UserName = "username",
          Password = "password",
      };
      
      Session session = new Session();
      session.Open(sessionOptions);
      
      if (session.FileExists("/remote/path/file.txt"))
      {
          Console.WriteLine("Exists");
      }
      else
      {
          Console.WriteLine("Does not exist");
      }
      

      (我是 WinSCP 的作者)

      【讨论】:

        【解决方案3】:

        我使用 FTPStatusCode.FileActionOK 来检查文件是否存在...

        然后,在“else”部分,返回 false。

        【讨论】:

          【解决方案4】:

          因为

          request.Method = WebRequestMethods.Ftp.GetFileSize
          

          在某些情况下可能会失败(550:在 ASCII 模式下不允许 SIZE),您可以改为检查时间戳。

          reqFTP.Credentials = new NetworkCredential(inf.LogOn, inf.Password);
          reqFTP.UseBinary = true;
          reqFTP.Method = WebRequestMethods.Ftp.GetDateTimestamp;
          

          【讨论】:

            【解决方案5】:
            var request = (FtpWebRequest)WebRequest.Create
                ("ftp://ftp.domain.com/doesntexist.txt");
            request.Credentials = new NetworkCredential("user", "pass");
            request.Method = WebRequestMethods.Ftp.GetFileSize;
            
            try
            {
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                FtpWebResponse response = (FtpWebResponse)ex.Response;
                if (response.StatusCode ==
                    FtpStatusCode.ActionNotTakenFileUnavailable)
                {
                    //Does not exist
                }
            }
            

            一般来说,像这样在代码中使用异常来实现功能是个坏主意,但是在这种情况下,我相信这是实用主义的胜利。在目录上调用列表可能比以这种方式使用异常效率低得多。

            如果你不是,请注意这不是一个好习惯!

            编辑:“它对我有用!”

            这似乎适用于大多数 ftp 服务器,但不是全部。有些服务器需要在 SIZE 命令起作用之前发送“TYPE I”。有人会认为问题应该如下解决:

            request.UseBinary = true;
            

            不幸的是,这是一个设计限制(大胖错误!),除非 FtpWebRequest 正在下载或上传文件,否则它不会发送“TYPE I”。请参阅讨论和 Microsoft 回复 here

            我建议改用以下 WebRequestMethod,这适用于我测试的所有服务器,即使是不会返回文件大小的服务器。

            WebRequestMethods.Ftp.GetDateTimestamp
            

            【讨论】:

              猜你喜欢
              • 2013-06-23
              • 1970-01-01
              • 2011-11-16
              • 1970-01-01
              • 2013-07-22
              • 2019-03-07
              • 2012-05-15
              相关资源
              最近更新 更多