FTPClient如何删除目录?
我想删除FTP中的文件夹。
可以将FTPClient
对象删除吗?
FtpWebRequest提供Delete操作。 这是一段代码来实现:
FtpWebRequest reqFTP = FtpWebRequest.Create(uri); // Credentials and login handling... reqFTP.Method = WebRequestMethods.Ftp.DeleteFile; string result = string.Empty; FtpWebResponse response = reqFTP.GetResponse(); long size = response.ContentLength; Stream datastream = response.GetResponseStream(); StreamReader sr = new StreamReader(datastream); result = sr.ReadToEnd(); sr.Close(); datastream.Close(); response.Close();
它应该适用于文件和目录。 确实,请检查您是否拥有正确的权限。
此外,如果文件夹不为空,则无法删除它们。 您必须递归遍历它们才能删除内容。
由于权限问题引发的exception并不总是很清楚……
要删除空目录,请使用FtpWebRequest
的RemoveDirectory
“方法”:
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
类(或.NET框架中的任何其他FTP实现)中不支持递归操作。 你必须自己实现递归:
- 列出远程目录
- 迭代条目,删除文件并递归到子目录(再次列出它们等)
棘手的部分是识别子目录中的文件。 使用FtpWebRequest
以便携方式无法做到这一点。 遗憾的是, FtpWebRequest
不支持MLSD
命令,这是在FTP协议中检索具有文件属性的目录列表的唯一可移植方式。 另请参阅检查FTP服务器上的对象是文件还是目录 。
你的选择是:
- 对文件名执行操作,该文件名肯定会对文件失败并对目录成功(反之亦然)。 即你可以尝试下载“名称”。 如果成功,它是一个文件,如果失败,它就是一个目录。 但是当您有大量条目时,这可能会成为性能问题。
- 您可能很幸运,在您的特定情况下,您可以通过文件名告诉目录中的文件(即所有文件都有扩展名,而子目录没有)
- 您使用长目录列表(
LIST
命令=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 lines = new List (); 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的作者)
我发现工作的唯一方法是依赖“WebRequestMethods.Ftp.DeleteFile”并且它会给文件夹或文件夹带有文件的exception,所以我在这里创建了一个新的interenal方法,以递归方式删除目录。
public void delete(string deleteFile) { try { /* Create an FTP Request */ ftpRequest = (FtpWebRequest)WebRequest.Create(host + "/" + deleteFile); /* Log in to the FTP Server with the User Name and Password Provided */ ftpRequest.Credentials = new NetworkCredential(user, pass); /* When in doubt, use these options */ ftpRequest.UseBinary = true; ftpRequest.UsePassive = true; ftpRequest.KeepAlive = true; /* Specify the Type of FTP Request */ ftpRequest.Method = WebRequestMethods.Ftp.DeleteFile; /* Establish Return Communication with the FTP Server */ ftpResponse = (FtpWebResponse)ftpRequest.GetResponse(); /* Resource Cleanup */ ftpResponse.Close(); ftpRequest = null; } catch (Exception ex) { //Console.WriteLine(ex.ToString()); try { deleteDirectory(deleteFile); } catch { } } return; }
和目录删除
/* Delete Directory*/ private void deleteDirectory(string directoryName) { try { //Check files inside var direcotryChildren = directoryListSimple(directoryName); if (direcotryChildren.Any() && (!string.IsNullOrWhiteSpace(direcotryChildren[0]))) { foreach (var child in direcotryChildren) { delete(directoryName + "/" + child); } } /* Create an FTP Request */ ftpRequest = (FtpWebRequest)WebRequest.Create(host + "/" + directoryName); /* Log in to the FTP Server with the User Name and Password Provided */ ftpRequest.Credentials = new NetworkCredential(user, pass); /* When in doubt, use these options */ ftpRequest.UseBinary = true; ftpRequest.UsePassive = true; ftpRequest.KeepAlive = true; /* Specify the Type of FTP Request */ ftpRequest.Method = WebRequestMethods.Ftp.RemoveDirectory; /* Establish Return Communication with the FTP Server */ ftpResponse = (FtpWebResponse)ftpRequest.GetResponse(); /* Resource Cleanup */ ftpResponse.Close(); ftpRequest = null; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return; }
列出Direcotry儿童
/* List Directory Contents File/Folder Name Only */ public string[] directoryListSimple(string directory) { try { /* Create an FTP Request */ ftpRequest = (FtpWebRequest)FtpWebRequest.Create(host + "/" + directory); /* Log in to the FTP Server with the User Name and Password Provided */ ftpRequest.Credentials = new NetworkCredential(user, pass); /* When in doubt, use these options */ ftpRequest.UseBinary = true; ftpRequest.UsePassive = true; ftpRequest.KeepAlive = true; /* Specify the Type of FTP Request */ ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory; /* Establish Return Communication with the FTP Server */ ftpResponse = (FtpWebResponse)ftpRequest.GetResponse(); /* Establish Return Communication with the FTP Server */ ftpStream = ftpResponse.GetResponseStream(); /* Get the FTP Server's Response Stream */ StreamReader ftpReader = new StreamReader(ftpStream); /* Store the Raw Response */ string directoryRaw = null; /* Read Each Line of the Response and Append a Pipe to Each Line for Easy Parsing */ try { while (ftpReader.Peek() != -1) { directoryRaw += ftpReader.ReadLine() + "|"; } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } /* Resource Cleanup */ ftpReader.Close(); ftpStream.Close(); ftpResponse.Close(); ftpRequest = null; /* Return the Directory Listing as a string Array by Parsing 'directoryRaw' with the Delimiter you Append (I use | in This Example) */ try { string[] directoryList = directoryRaw.Split("|".ToCharArray()); return directoryList; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } /* Return an Empty string Array if an Exception Occurs */ return new string[] { "" }; } /* List Directory Contents in Detail (Name, Size, Created, etc.) */ public string[] directoryListDetailed(string directory) { try { /* Create an FTP Request */ ftpRequest = (FtpWebRequest)FtpWebRequest.Create(host + "/" + directory); /* Log in to the FTP Server with the User Name and Password Provided */ ftpRequest.Credentials = new NetworkCredential(user, pass); /* When in doubt, use these options */ ftpRequest.UseBinary = true; ftpRequest.UsePassive = true; ftpRequest.KeepAlive = true; /* Specify the Type of FTP Request */ ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails; /* Establish Return Communication with the FTP Server */ ftpResponse = (FtpWebResponse)ftpRequest.GetResponse(); /* Establish Return Communication with the FTP Server */ ftpStream = ftpResponse.GetResponseStream(); /* Get the FTP Server's Response Stream */ StreamReader ftpReader = new StreamReader(ftpStream); /* Store the Raw Response */ string directoryRaw = null; /* Read Each Line of the Response and Append a Pipe to Each Line for Easy Parsing */ try { while (ftpReader.Peek() != -1) { directoryRaw += ftpReader.ReadLine() + "|"; } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } /* Resource Cleanup */ ftpReader.Close(); ftpStream.Close(); ftpResponse.Close(); ftpRequest = null; /* Return the Directory Listing as a string Array by Parsing 'directoryRaw' with the Delimiter you Append (I use | in This Example) */ try { string[] directoryList = directoryRaw.Split("|".ToCharArray()); return directoryList; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } /* Return an Empty string Array if an Exception Occurs */ return new string[] { "" }; }
很重要的一点
正如刚才提到的..
当文件夹不为空时,您无法删除它们。 您必须递归遍历它们才能删除内容。
public void Deletedir(string remoteFolder) { try { /* Create an FTP Request */ ftpRequest = (FtpWebRequest)FtpWebRequest.Create(host + "/"+ remoteFolder); /* Log in to the FTP Server with the User Name and Password Provided */ ftpRequest.Credentials = new NetworkCredential(user, pass); /* When in doubt, use these options */ ftpRequest.UseBinary = true;***strong text*** ftpRequest.UsePassive = true; ftpRequest.KeepAlive = true; /* Specify the Type of FTP Request */ ftpRequest.Method = WebRequestMethods.Ftp.RemoveDirectory; /* Establish Return Communication with the FTP Server */ ftpResponse = (FtpWebResponse)ftpRequest.GetResponse(); /* Get the FTP Server's Response Stream */ ftpStream = ftpResponse.GetResponseStream(); /* Open a File Stream to Write the Downloaded File */ } catch { } }
这是你可以使用的代码。 这里是你如何使用它,例如,点击按钮。
private void button5_Click(object sender, EventArgs e) { ftp ftpClient = new ftp(@"SERVICE PROVIDER", "USERNAME", "PASSWORD"); ftpClient.Deletedir("DIRECTORY U WANT TO DELETE"); }
请记住,您的文件夹应该是EMPTY。