我试过这个,
Const localFile As String = "C:\Documents and Settings\cr\Desktop\T\New Folder\" Const remoteFile As String = "textBox.Text" Const host As String = "ftp://ftp.example.com" Const username As String = "username" Const password As String = "password" For i1 = 0 To ListBox1.SelectedItems.Count - 1 Dim li As New ListViewItem li = ListView1.Items.Add(ListBox1.SelectedItems(i1)) Dim URI1 As String = host + remoteFile & "/" & ListBox1.SelectedItems(i1) Dim ftp1 As System.Net.FtpWebRequest = CType(FtpWebRequest.Create(URI1),FtpWebRequest) ftp1.Credentials = New System.Net.NetworkCredential(username,password) ftp1.KeepAlive = False ftp1.UseBinary = True ftp1.Method = System.Net.WebRequestMethods.Ftp.DownloadFile Using response As System.Net.FtpWebResponse = CType(ftp1.GetResponse,System.Net.FtpWebResponse) Using responseStream As IO.Stream = response.GetResponseStream Dim length As Integer = response.ContentLength Dim bytes(length) As Byte 'loop to read & write to file Using fs As New IO.FileStream(localFile & ListBox1.SelectedItems(i1),IO.FileMode.Create) Dim buffer(2047) As Byte Dim read As Integer = 1 Do read = responseStream.Read(buffer,buffer.Length) fs.Write(buffer,read) Loop Until read = 0 'see Note(1) responseStream.Close() fs.Flush() fs.Close() End Using responseStream.Close() End Using response.Close() End Using li.BackColor = Color.Aquamarine Next
但问题是我可以从文件夹下载多个文件,但无法从主目录下载子目录及其内容.
基本上,主目录由文件和子目录组成.那么是否有任何可能的方法从FTP下载子目录及其内容?
提前致谢.
解决方法
FtpWebRequest没有任何明确支持递归文件下载(或任何其他递归操作).你必须自己实现递归:
>列出远程目录
>迭代条目,下载文件并递归到子目录(再次列出它们等)
一个棘手的部分是识别子目录中的文件.使用FtpWebRequest以便携方式无法做到这一点.遗憾的是,FtpWebRequest不支持MLSD命令,这是在FTP协议中检索具有文件属性的目录列表的唯一可移植方式.另见Checking if object on FTP server is file or directory.
你的选择是:
>对文件名执行操作,该文件名肯定会对文件失败并对目录成功(反之亦然).即你可以尝试下载“名称”.如果成功,它是一个文件,如果失败,它就是一个目录.
>您可能很幸运,在您的具体情况下,您可以通过文件名告诉目录中的文件(即所有文件都有扩展名,而子目录则没有)
>您使用长目录列表(LIST命令= ListDirectoryDetails方法)并尝试解析特定于服务器的列表.许多FTP服务器使用* nix样式列表,您可以在条目的最开头通过d标识目录.但是许多服务器使用不同的格式.以下示例使用此方法(假设为* nix格式)
Sub DownloadFtpDirectory( url As String,credentials As NetworkCredential,localPath As String) Dim listRequest As FtpWebRequest = WebRequest.Create(url) listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails listRequest.Credentials = credentials Dim lines As List(Of String) = New List(Of String) Using listResponse As FtpWebResponse = listRequest.GetResponse(),listStream As Stream = listResponse.GetResponseStream(),listReader As StreamReader = New StreamReader(listStream) While Not listReader.EndOfStream lines.Add(listReader.ReadLine()) End While End Using For Each line As String In lines Dim tokens As String() = line.Split(New Char() {" "},9,StringSplitOptions.RemoveEmptyEntries) Dim name As String = tokens(8) Dim permissions As String = tokens(0) Dim localFilePath As String = Path.Combine(localPath,name) Dim fileUrl As String = url + name If permissions(0) = "d" Then If Not Directory.Exists(localFilePath) Then Directory.CreateDirectory(localFilePath) End If DownloadFtpDirectory(fileUrl + "/",credentials,localFilePath) Else Dim downloadRequest As FtpWebRequest = WebRequest.Create(fileUrl) downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile downloadRequest.Credentials = credentials Using downloadResponse As FtpWebResponse = downloadRequest.GetResponse(),sourceStream As Stream = downloadResponse.GetResponseStream(),targetStream As Stream = File.Create(localFilePath) Dim buffer As Byte() = New Byte(10240 - 1) {} Dim read As Integer Do read = sourceStream.Read(buffer,buffer.Length) If read > 0 Then targetStream.Write(buffer,read) End If Loop While read > 0 End Using End If Next End Sub
使用如下功能:
Dim credentials As NetworkCredential = New NetworkCredential("user","mypassword") Dim url As String = "ftp://ftp.example.com/directory/to/download/" DownloadFtpDirectory(url,"C:\target\directory")
如果要避免解析特定于服务器的目录列表格式的麻烦,请使用支持MLSD命令和/或解析各种LIST列表格式的第三方库;和递归下载.
例如,使用WinSCP .NET assembly,您可以通过一次调用Session.GetFiles
下载整个目录:
' Setup session options Dim SessionOptions As SessionOptions = New SessionOptions With SessionOptions .Protocol = Protocol.Ftp .HostName = "ftp.example.com" .UserName = "user" .Password = "mypassword" End With Using session As Session = New Session() ' Connect session.Open(SessionOptions) ' Download files session.GetFiles("/directory/to/download/*","C:\target\directory\*").Check() End Using
在内部,如果服务器支持,WinSCP使用MLSD命令.如果没有,它使用LIST命令并支持许多不同的列表格式.
默认情况下,Session.GetFiles
method是递归的.
(我是WinSCP的作者)