如何在使用FtpWebRequest之前检查FTP上的文件是否存在

70

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

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

5个回答

123
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;

很不幸,这是一个设计限制(大大的Bug!),除非FtpWebRequest正在下载或上传文件,否则它不会发送"TYPE I"。请参阅讨论和Microsoft响应此处

我建议改用以下的WebRequestMethod,在我测试的所有服务器上都有效,即使那些无法返回文件大小的服务器也可以。

WebRequestMethods.Ftp.GetDateTimestamp

12

因为

request.Method = WebRequestMethods.Ftp.GetFileSize

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

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

7

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);
    }
}

如果你想要更简单的代码,可以使用一些第三方FTP库。比如说WinSCP .NET assembly,你可以使用它的Session.FileExists方法
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的作者)


0
你可以使用 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");
    }

-1

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接