Чтобы удалить пустой каталог, используйте RemoveDirectory
"метод" из FtpWebRequest
:
void DeleteFtpDirectory(string url, NetworkCredential credentials)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
request.Method = WebRequestMethods.Ftp.RemoveDirectory;
request.Credentials = credentials;
request.GetResponse().Close();
}
используйте его как:
string url = "ftp://ftp.example.com/directory/todelete";
NetworkCredential credentials = new NetworkCredential("username", "password");
DeleteFtpDirectory(url, credentials);
Хотя этостановится намного сложнее, если вам нужно удалить непустую директорию.В классе FtpWebRequest
нет поддержки рекурсивных операций (или любой другой реализации FTP в .NET Framework).Вы должны реализовать рекурсию самостоятельно:
- Вывести список удаленных каталогов
- Итерировать записи, удалять файлы и повторять их в подкаталогах (перечислять их снова и т.д.)
Сложная задача - определить файлы из подкаталогов.Нет способа сделать это портативным способом с FtpWebRequest
.К сожалению, FtpWebRequest
не поддерживает команду MLSD
, которая является единственным переносимым способом получения списка каталогов с атрибутами файлов в протоколе FTP.См. Также Проверка, является ли объект на FTP-сервере файлом или каталогом .
Возможны следующие варианты:
- Выполнить операцию с именем файла, которая наверняка не будет выполнена.для файла и успешно для каталогов (или наоборот).Т.е. вы можете попробовать скачать «имя».Если это удается, это файл, если это не удается, это каталог.Но это может стать проблемой производительности, когда у вас есть большое количество записей.
- Вам может повезти, и в вашем конкретном случае вы можете отличить файл из каталога по имени файла (т.е. все ваши файлыиметь расширение, а подкаталоги - нет)
- Вы используете длинный список каталогов (
LIST
command = ListDirectoryDetails
метод) и пытаетесь проанализировать список, специфичный для сервера.Многие FTP-серверы используют листинг в стиле * nix, где вы идентифицируете каталог по d
в самом начале записи.Но многие серверы используют другой формат.В следующем примере используется этот подход (в предположении формата * nix). - В этом конкретном случае вы можете просто попытаться удалить запись в виде файла.Если удаление не удалось, попробуйте перечислить запись как каталог.Если листинг завершается успешно, вы предполагаете, что это папка, и действуйте соответственноК сожалению, некоторые серверы не выдают ошибку, когда вы пытаетесь перечислить файл.Они просто вернут список с одной записью для файла.
static void DeleteFtpDirectory(string url, NetworkCredential credentials)
{
FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(url);
listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
listRequest.Credentials = credentials;
List<string> lines = new List<string>();
using (FtpWebResponse listResponse = (FtpWebResponse)listRequest.GetResponse())
using (Stream listStream = listResponse.GetResponseStream())
using (StreamReader listReader = new StreamReader(listStream))
{
while (!listReader.EndOfStream)
{
lines.Add(listReader.ReadLine());
}
}
foreach (string line in lines)
{
string[] tokens =
line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
string name = tokens[8];
string permissions = tokens[0];
string fileUrl = url + name;
if (permissions[0] == 'd')
{
DeleteFtpDirectory(fileUrl + "/", credentials);
}
else
{
FtpWebRequest deleteRequest = (FtpWebRequest)WebRequest.Create(fileUrl);
deleteRequest.Method = WebRequestMethods.Ftp.DeleteFile;
deleteRequest.Credentials = credentials;
deleteRequest.GetResponse();
}
}
FtpWebRequest removeRequest = (FtpWebRequest)WebRequest.Create(url);
removeRequest.Method = WebRequestMethods.Ftp.RemoveDirectory;
removeRequest.Credentials = credentials;
removeRequest.GetResponse();
}
Используйте его так же, как и в предыдущей (плоской) реализации.
Или используйте стороннюю библиотеку, которая поддерживает рекурсивные операции.
Например, WinSCP .NET сборка вы можете удалить весь каталог одним вызовом Session.RemoveFiles
:
// 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);
// Delete folder
session.RemoveFiles("/directory/todelete").Check();
}
Внутренне WinSCP использует MLSD
команда, если поддерживается сервером.Если нет, он использует команду LIST
и поддерживает десятки различных форматов листинга.
(я автор WinSCP)