vb.net 如何使用VB.NET从FTP下载目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22626766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to download directories from FTP using VB.NET
提问by Jigar patel
I am trying to download multiple directories from FTP server to my local machine,
我正在尝试将多个目录从 FTP 服务器下载到我的本地机器,
I have tried this,
我试过这个,
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
But here the problem is that I am able to download multiple files from folders, but unable to download the sub directories and their contents from the main directory.
但这里的问题是我可以从文件夹下载多个文件,但无法从主目录下载子目录及其内容。
Basically the main directory consist of files and sub directories both. So is there any possible way to download sub directory and its contents from FTP?
基本上主目录由文件和子目录组成。那么有没有办法从FTP下载子目录及其内容?
Thanks in advance.
提前致谢。
回答by Martin Prikryl
Translating my answer to C# Download all files and subdirectories through FTPto VB.NET:
翻译我对C# 的回答通过 FTP将所有文件和子目录下载到 VB.NET:
The FtpWebRequestdoes not have any explicit support for recursive file download (or any other recursive operation). You have to implement the recursion yourself:
在FtpWebRequest没有递归文件下载(或任何其他递归运算)的任何明确的支持。您必须自己实现递归:
- List the remote directory
- Iterate the entries, downloading files and recursing into subdirectories (listing them again, etc.)
- 列出远程目录
- 迭代条目,下载文件并递归到子目录(再次列出它们等)
A tricky part is to identify files from subdirectories. There's no way to do that in a portable way with the FtpWebRequest. The FtpWebRequestunfortunately does not support the MLSDcommand, which is the only portable way to retrieve directory listing with file attributes in FTP protocol. See also Checking if object on FTP server is file or directory.
一个棘手的部分是从子目录中识别文件。使用FtpWebRequest. 该FtpWebRequest遗憾的是不支持的MLSD命令,这是检索目录与FTP协议的文件属性上市的唯一可移植的方法。另请参阅检查 FTP 服务器上的对象是文件还是目录。
Your options are:
您的选择是:
- Do an operation on a file name that is certain to fail for file and succeeds for directories (or vice versa). I.e. you can try to download the "name". If that succeeds, it's a file, if that fails, it's a directory.
- You may be lucky and in your specific case, you can tell a file from a directory by a file name (i.e. all your files have an extension, while subdirectories do not)
- You use a long directory listing (
LISTcommand =ListDirectoryDetailsmethod) and try to parse a server-specific listing. Many FTP servers use *nix-style listing, where you identify a directory by thedat the very beginning of the entry. But many servers use a different format. The following example uses this approach (assuming the *nix format)
- 对文件名进行操作,对于文件肯定会失败而对于目录会成功(反之亦然)。即您可以尝试下载“名称”。如果成功,它是一个文件,如果失败,它是一个目录。
- 您可能很幸运,在您的特定情况下,您可以通过文件名区分目录中的文件(即所有文件都有扩展名,而子目录没有)
- 您使用长目录列表(
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, 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
Use the function like:
使用如下函数:
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")
If you want to avoid troubles with parsing the server-specific directory listing formats, use a 3rd party library that supports the MLSDcommand and/or parsing various LISTlisting formats; and recursive downloads.
如果您想避免解析特定于服务器的目录列表格式的麻烦,请使用支持MLSD命令和/或解析各种LIST列表格式的第 3 方库;和递归下载。
For example with WinSCP .NET assemblyyou can download whole directory with a single call to the Session.GetFiles:
例如,使用WinSCP .NET 程序集,您只需调用一次即可下载整个目录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
Internally, WinSCP uses the MLSDcommand, if supported by the server. If not, it uses the LISTcommand and supports dozens of different listing formats.
MLSD如果服务器支持,WinSCP 在内部使用该命令。如果没有,它会使用该LIST命令并支持数十种不同的列表格式。
The Session.GetFilesmethodis recursive by default.
该Session.GetFiles方法默认是递归的。
(I'm the author of WinSCP)
(我是 WinSCP 的作者)
回答by THE AMAZING
Check out my FTP class: Its pretty straight forward.
查看我的 FTP 课程:非常简单。
Take a look at my FTP class, it might be exactly what you need.
看看我的 FTP 类,它可能正是您所需要的。
Public Class FTP
'-------------------------[BroCode]--------------------------
'----------------------------FTP-----------------------------
Private _credentials As System.Net.NetworkCredential
Sub New(ByVal _FTPUser As String, ByVal _FTPPass As String)
setCredentials(_FTPUser, _FTPPass)
End Sub
Public Sub UploadFile(ByVal _FileName As String, ByVal _UploadPath As String)
Dim _FileInfo As New System.IO.FileInfo(_FileName)
Dim _FtpWebRequest As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(New Uri(_UploadPath)), System.Net.FtpWebRequest)
_FtpWebRequest.Credentials = _credentials
_FtpWebRequest.KeepAlive = False
_FtpWebRequest.Timeout = 20000
_FtpWebRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
_FtpWebRequest.UseBinary = True
_FtpWebRequest.ContentLength = _FileInfo.Length
Dim buffLength As Integer = 2048
Dim buff(buffLength - 1) As Byte
Dim _FileStream As System.IO.FileStream = _FileInfo.OpenRead()
Try
Dim _Stream As System.IO.Stream = _FtpWebRequest.GetRequestStream()
Dim contentLen As Integer = _FileStream.Read(buff, 0, buffLength)
Do While contentLen <> 0
_Stream.Write(buff, 0, contentLen)
contentLen = _FileStream.Read(buff, 0, buffLength)
Loop
_Stream.Close()
_Stream.Dispose()
_FileStream.Close()
_FileStream.Dispose()
Catch ex As Exception
MessageBox.Show(ex.Message, "Upload Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Public Sub DownloadFile(ByVal _FileName As String, ByVal _ftpDownloadPath As String)
Try
Dim _request As System.Net.FtpWebRequest = System.Net.WebRequest.Create(_ftpDownloadPath)
_request.KeepAlive = False
_request.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
_request.Credentials = _credentials
Dim _response As System.Net.FtpWebResponse = _request.GetResponse()
Dim responseStream As System.IO.Stream = _response.GetResponseStream()
Dim fs As New System.IO.FileStream(_FileName, System.IO.FileMode.Create)
responseStream.CopyTo(fs)
responseStream.Close()
_response.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "Download Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Public Function GetDirectory(ByVal _ftpPath As String) As List(Of String)
Dim ret As New List(Of String)
Try
Dim _request As System.Net.FtpWebRequest = System.Net.WebRequest.Create(_ftpPath)
_request.KeepAlive = False
_request.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails
_request.Credentials = _credentials
Dim _response As System.Net.FtpWebResponse = _request.GetResponse()
Dim responseStream As System.IO.Stream = _response.GetResponseStream()
Dim _reader As System.IO.StreamReader = New System.IO.StreamReader(responseStream)
Dim FileData As String = _reader.ReadToEnd
Dim Lines() As String = FileData.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
For Each l As String In Lines
ret.Add(l)
Next
_reader.Close()
_response.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "Directory Fetch Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Return ret
End Function
Private Sub setCredentials(ByVal _FTPUser As String, ByVal _FTPPass As String)
_credentials = New System.Net.NetworkCredential(_FTPUser, _FTPPass)
End Sub
End Class
To initialize:
初始化:
Dim ftp As New FORM.FTP("username", "password")
ftp.UploadFile("c:\file.jpeg", "ftp://domain/file.jpeg")
ftp.DownloadFile("c:\file.jpeg", "ftp://ftp://domain/file.jpeg")
Dim directory As List(Of String) = ftp.GetDirectory("ftp://ftp.domain.net/")
ListBox1.Items.Clear()
For Each item As String In directory
ListBox1.Items.Add(item)
Next

