Мне нужно использовать FtpWebRequest
чтобы поместить файл в каталог FTP. Перед загрузкой я хотел бы сначала узнать, существует ли этот файл.
Какой метод или свойство следует использовать для проверки наличия этого файла?
Мне нужно использовать FtpWebRequest
чтобы поместить файл в каталог FTP. Перед загрузкой я хотел бы сначала узнать, существует ли этот файл.
Какой метод или свойство следует использовать для проверки наличия этого файла?
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
}
}
Как правило, это плохая идея использовать Исключения для функциональности в вашем коде, как это, но в этом случае я считаю это победой для прагматизма. Список вызовов в каталоге может оказаться более неэффективным, чем использование исключений таким образом.
Если вы этого не сделаете, просто знайте, что это не хорошая практика!
EDIT: "Это работает для меня!"
Это похоже на работу на большинстве ftp-серверов, но не на всех. Некоторые серверы требуют отправки "ТИПА I" до того, как команда SIZE будет работать. Казалось бы, проблема должна быть решена следующим образом:
request.UseBinary = true;
К сожалению, это ограничение по дизайну (большая толстая ошибка!), если FtpWebRequest не загружает или не загружает файл, он НЕ отправляет "ТИП I". См. Обсуждение и ответ Microsoft здесь.
Вместо этого я рекомендую использовать следующий WebRequestMethod, это работает для меня на всех проверенных серверах, даже тех, которые не возвращают размер файла.
WebRequestMethods.Ftp.GetDateTimestamp
Поскольку
request.Method = WebRequestMethods.Ftp.GetFileSize
может произойти сбой в некотором случае (550: SIZE не разрешен в режиме ASCII), вы можете просто проверить Timestamp вместо этого.
reqFTP.Credentials = new NetworkCredential(inf.LogOn, inf.Password);
reqFTP.UseBinary = true;
reqFTP.Method = WebRequestMethods.Ftp.GetDateTimestamp;
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)
Я использую FTPStatusCode.FileActionOK, чтобы проверить, существует ли файл...
то в разделе "else" верните false.