我正在尝试将多个目录从 FTP 服务器下载到我的本地计算机,
我已经尝试过了,
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, 0, buffer.Length)
fs.Write(buffer, 0, 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 下载子目录及其内容?
提前致谢。
最佳答案
将我的答案翻译为 C# Download all files and subdirectories through FTP VB.NET:
FtpWebRequest
没有对递归文件下载(或任何其他递归操作)的任何明确支持。您必须自己实现递归:
- 列出远程目录
- 迭代条目、下载文件并递归到子目录(再次列出它们等)
一个棘手的部分是识别子目录中的文件。无法使用 FtpWebRequest
以可移植的方式做到这一点。不幸的是,FtpWebRequest
不支持 MLSD
命令,这是在 FTP 协议(protocol)中检索具有文件属性的目录列表的唯一可移植方法。另请参阅Checking if object on FTP server is file or directory .
您的选择是:
- 对文件名执行的操作对于文件肯定会失败,而对于目录则成功(反之亦然)。 IE。你可以尝试下载“名字”。如果成功,它是一个文件,如果失败,它是一个目录。
- 您可能很幸运,在您的具体情况下,您可以通过文件名区分文件和目录(即所有文件都有扩展名,而子目录没有)
- 您使用长目录列表(
LIST
command =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, 0, buffer.Length)
If read > 0 Then
targetStream.Write(buffer, 0, 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, credentials, "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 的作者)
关于.net - 如何使用 VB.NET 从 FTP 下载目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22626766/