繁体   English   中英

从VB.NET的FTP文件夹下载所有文件和子目录

[英]Download all files and sub-directories from FTP folder in VB.NET

我在整个互联网上搜索了有关我的问题的信息,但是我只找到了C#的答案,却没有找到VB.NET的答案。

我想下载FTP服务器上目录的所有文件和子目录。

我目前正在通过从FTP服务器下载ZIP文件并解压缩来做到这一点,但这不是一个好方法。

谢谢!

我知道您可能会懒惰地阅读所有内容,但这是答案!!! 代码在末尾:D

你好,

使用可用于C#和VB.NET的WinSCP库非常简单-这是完整的答案:

首先,将WinSCP库安装到您的项目中,请参见此处: https ://winscp.net/eng/docs/library#downloading_and_installing_the_assembly

或者,如果您不愿意这样做,则只需下载该库,然后将DLL文件添加为项目中的引用即可。

现在,让我们将整个目录(包括其文件及其子目录)下载到本地存储中。

您有2个选择:

  • 即使已下载文件和目录,也要下载Session.GetFiles

  • Session.SynchronizeDirectories来下载文件和目录(如果不存在),还将下载已存在的已修改文件。 (最好,比第一个选项更好)。

我当然选择了第二个选项,因为它是有史以来最好的一个。 但是,如果要使用Session.GetFiles方法...,可以在此处查看VB.NET示例: https : //winscp.net/eng/docs/library_session_getfiles#vbnet

这是我使用第二个选项的方式: https : //winscp.net/eng/docs/faq_script_modified_files

如您所见,一切解释都很棒!

基本上使用synchronize local而不是get synchronize remotesynchronize remote而不是put synchronize remote

通过WinSCP .NET程序集,可以使用Session.SynchronizeDirectories,并将参数模式分别设置为SynchronizationMode.Remote或SynchronizationMode.Local而不是Session.GetFiles或Session.PutFiles。

当我想将文件从FTP服务器下载到我的本地PC时,这就是我使用的文件(SynchronizeDirectories):

  1. 是的! 当然首先Imports WinSCP :-)
  2. 请使用此代码,因为https://winscp.net/eng/docs/library_session_synchronizedirectories#vbnet上的代码适用于SFTP(端口22)而不适用于FTP(端口21)...,并且它还使用SynchronizeMode.Remote ,该文件从您的PC到FTP服务器,因此在下面的代码中,我将.Remote替换为.Local

     Public Shared Function Main() As Integer Try ' Setup session options Dim sessionOptions As New SessionOptions With sessionOptions .Protocol = Protocol.Ftp .HostName = "example.com" .UserName = "user" .Password = "mypassword" End With Using session As New Session ' Will continuously report progress of synchronization AddHandler session.FileTransferred, AddressOf FileTransferred ' Connect session.Open(sessionOptions) ' Synchronize files Dim synchronizationResult As SynchronizationResult synchronizationResult = _ session.SynchronizeDirectories( _ SynchronizationMode.Local, "d:\\www", "/home/martin/public_html", False) ' Throw on any error synchronizationResult.Check() End Using Return 0 Catch e As Exception Console.WriteLine("Error: {0}", e) Return 1 End Try End Function Private Shared Sub FileTransferred(ByVal sender As Object, ByVal e As TransferEventArgs) If e.Error Is Nothing Then 'Console.WriteLine("Upload of {0} succeeded", e.FileName) Else 'Console.WriteLine("Upload of {0} failed: {1}", e.FileName, e.Error) End If If e.Chmod IsNot Nothing Then If e.Chmod.Error Is Nothing Then 'Console.WriteLine("Permisions of {0} set to {1}", e.Chmod.FileName, e.Chmod.FilePermissions) Else 'Console.WriteLine("Setting permissions of {0} failed: {1}", e.Chmod.FileName, e.Chmod.Error) End If Else 'Console.WriteLine("Permissions of {0} kept with their defaults", e.Destination) End If If e.Touch IsNot Nothing Then If e.Touch.Error Is Nothing Then 'Console.WriteLine("Timestamp of {0} set to {1}", e.Touch.FileName, e.Touch.LastWriteTime) Else 'Console.WriteLine("Setting timestamp of {0} failed: {1}", e.Touch.FileName, e.Touch.Error) End If Else ' This should never happen during "local to remote" synchronization 'Console.WriteLine("Timestamp of {0} kept with its default (current time)", e.Destination) End If End Sub 

不要忘记替换凭据和路径。

还有一件事? 祝您项目顺利! :-)

将我的答案翻译成C#,通过FTP所有文件和子目录下载到VB.NET:

FtpWebRequest对递归文件操作(包括下载)没有任何显式支持。 您必须自己实现递归:

  • 列出远程目录
  • 迭代条目,下载文件并递归到子目录(再次列出它们,等等)

棘手的部分是从子目录中识别文件。 使用FtpWebRequest无法以可移植的方式完成此操作。 不幸的是, FtpWebRequest不支持MLSD命令,这是在FTP协议中检索带有文件属性的目录列表的唯一便携式方法。 另请参阅检查FTP服务器上的对象是文件还是目录

您的选择是:

  • 对一定要对文件失败但对目录成功的文件名执行操作(反之亦然)。 即,您可以尝试下载“名称”。 如果成功,则为文件;如果失败,则为目录。
  • 您可能很幸运,在您的特定情况下,您可以通过文件名告诉目录中的文件(即,所有文件都有扩展名,而子目录则没有)
  • 您使用长目录列表( 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

使用如下功能:

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程序集,您只需一次调用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方法是递归的。

(我是WinSCP的作者)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM