Как проверить, существует ли файл на FTP перед FtpWebRequest - PullRequest
66 голосов
/ 07 декабря 2008

Мне нужно использовать FtpWebRequest, чтобы поместить файл в каталог FTP. Перед загрузкой я хотел бы сначала узнать, существует ли этот файл.

Какой метод или свойство я должен использовать, чтобы проверить, существует ли этот файл?

Ответы [ 4 ]

112 голосов
/ 08 декабря 2008
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
    }
}

Как правило, это плохая идея использовать исключения для функциональности в вашем коде, как это, но в этом случае я считаю, что это победа для прагматизма. Список вызовов в каталоге может быть FAR более неэффективным, чем использование исключений таким образом.

Если нет, просто знайте, что это не очень хорошая практика!

РЕДАКТИРОВАТЬ: "Это работает для меня!"

Это работает на большинстве ftp-серверов, но не на всех. Некоторые серверы требуют отправки «TYPE I», прежде чем команда SIZE будет работать. Казалось бы, проблему нужно решить следующим образом:

request.UseBinary = true;

К сожалению, это конструктивное ограничение (большая полная ошибка!), Что если FtpWebRequest не загружает или не загружает файл, он НЕ будет отправлять «ТИП I». Смотрите обсуждение и ответ Microsoft здесь .

Я бы порекомендовал использовать следующий WebRequestMethod, он работает для меня на всех протестированных мной серверах, даже на тех, которые не возвращают размер файла.

WebRequestMethods.Ftp.GetDateTimestamp
7 голосов
/ 16 сентября 2015

Потому что

request.Method = WebRequestMethods.Ftp.GetFileSize

в некоторых случаях может завершиться ошибкой (550: РАЗМЕР не разрешен в режиме ASCII), вместо этого вы можете просто проверить метку времени.

reqFTP.Credentials = new NetworkCredential(inf.LogOn, inf.Password);
reqFTP.UseBinary = true;
reqFTP.Method = WebRequestMethods.Ftp.GetDateTimestamp;
2 голосов
/ 27 апреля 2018

FtpWebRequest (ни один другой класс в .NET) не имеет явного метода для проверки существования файла. Вам необходимо злоупотребить запросом типа GetFileSize или GetDateTimestamp.

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 сборка , вы можете использовать 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 голосов
/ 10 декабря 2017

Я использую FTPStatusCode.FileActionOK, чтобы проверить, существует ли файл ...

затем в разделе "else" верните false.

...