Fun with FTP in vb.net

Since GE Healthcare has us working in 1.1 of the framework these days, I don’

t have the advantage of using the packaged FTP control. But I have gotten one written using 2.0 technology now that will be far superior to the class I have been using. We will at some point be upgrading our applications to the new version of the framework and hopefully soon cause I am excited to begin working with the new tools.


Join me on Facebook

' Add a reference to Microsoft.mshtml to the project. 
 
Imports System
Imports System.IO
Imports System.Net
Imports System.Text.RegularExpressions
Imports System.Web
 
Public Class FtpProcessor
 
  Private Const BLOCK_SIZE As Integer = 4096
 
  Public Shared Function ListDirectory(ByVal host As String, ByVal remoteDirectory As String) As List(Of FtpDirectoryEntry)
    Return ListDirectory(host, remoteDirectory, "", "")
  End Function
 
  ''' <summary>
  ''' Get a directory listing from the FTP server.  Parse the HTML response
  ''' to build a list of FtpDirectoryEntry objects describing each entry.
  ''' </summary>
  ''' <returns>A list of FTP server directory entries.</returns>
  Public Shared Function ListDirectory(ByVal host As String, ByVal remoteDirectory As String, ByVal userName As String, ByVal password As String) As List(Of FtpDirectoryEntry)
 
    ' Build the URL to point to the remote file to download
    Dim uri As String = FormatHost(host) & remoteDirectory
 
    ' Build an FTP request to download the file
    Dim request As FtpWebRequest = CType(FtpWebRequest.Create(uri), FtpWebRequest)
 
    ' Setup the request.
    request.Method = WebRequestMethods.Ftp.ListDirectory
    request.KeepAlive = False
 
    InitializeRequest(request, uri, userName, password)
 
    ' Get the response from the FTP server
    Using response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
 
      ' Get the file stream from the response.
      Using stream As Stream = response.GetResponseStream()
        Using reader As New StreamReader(stream)
          Dim commandResult As String = reader.ReadToEnd()
          Return ParseAnchors(commandResult)
        End Using
      End Using
 
    End Using
 
    Return Nothing
 
  End Function
 
  Public Shared Sub DownloadFile(ByVal host As String, ByVal remoteFile As String, ByVal localFile As String)
    DownloadFile(host, remoteFile, localFile, "", "")
  End Sub
 
  ''' <summary>
  ''' Download the remote file to the local file name.
  ''' </summary>
  Public Shared Sub DownloadFile(ByVal host As String, ByVal remoteFile As String, ByVal localFile As String, ByVal userName As String, ByVal password As String)
 
    ' Build the URL to point to the remote file to download
    Dim uri As String = FormatHost(host) & " " & remoteFile
 
    ' Build an FTP request to download the file
    Dim request As FtpWebRequest = CType(FtpWebRequest.Create(uri), FtpWebRequest)
 
    ' Setup the request.
    request.Method = WebRequestMethods.Ftp.DownloadFile
 
    InitializeRequest(request, uri, userName, password)
 
    ' Get the response from the FTP server
    Using response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
 
      ' Get the file stream from the response.
      Using input As Stream = response.GetResponseStream()
 
        ' Save the file stream to a local file
        Using output As New FileStream(localFile, FileMode.CreateNew)
 
          ' Read the input file stream from the response.
          Using reader As New BinaryReader(input)
 
            ' Write the input file stream to the output file, one block at a time.
            Using writer As New BinaryWriter(output)
              While reader.PeekChar() <> -1
                writer.Write(reader.ReadBytes(BLOCK_SIZE))
              End While
            End Using
          End Using
        End Using
      End Using
    End Using
  End Sub
 
  Public Shared Function UploadFile(ByVal host As String, ByVal remoteFile As String, ByVal localFile As String) As String
    Return UploadFile(host, remoteFile, localFile, "", "")
  End Function
 
  ''' <summary>
  ''' Upload the local file to the host as the remote file.
  ''' </summary>
  ''' <returns>Status description from the server response.</returns>
  Public Shared Function UploadFile(ByVal host As String, ByVal remoteFile As String, ByVal localFile As String, _
    ByVal userName As String, ByVal password As String) As String
 
    Dim uri As String = FormatHost(host) & " " & remoteFile
    Dim contentLength As Long = New FileInfo(localFile).Length
 
    Dim request As FtpWebRequest = CType(WebRequest.Create(uri), FtpWebRequest)
 
    InitializeRequest(request, uri, userName, password)
 
    request.ContentLength = contentLength
 
    request.Method = WebRequestMethods.Ftp.UploadFile
 
    Using localStream As New FileStream(localFile, FileMode.Open, FileAccess.Read, FileShare.None)
      Using reader As New BinaryReader(localStream)
 
        Using uploadStream As Stream = request.GetRequestStream()
          Using writer As New BinaryWriter(uploadStream)
            For count As Long = 0 To contentLength Step BLOCK_SIZE
              writer.Write(reader.ReadBytes(BLOCK_SIZE))
            Next count
          End Using
        End Using
      End Using
    End Using
 
    Using response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
      Return response.StatusDescription
    End Using
 
  End Function
 
  ''' <summary>
  ''' Make sure that the host is in the format ftp://host/
  ''' </summary>
  Private Shared Function FormatHost(ByVal host As String) As String
    host = host.Trim().ToLower().TrimStart("//").TrimStart("\\").TrimEnd("\")
    If Not host.StartsWith("ftp://") Then
      host = "ftp://" & host
    End If
 
    If Not host.EndsWith("/") Then
      host &= "/"
    End If
 
    Return host
  End Function
 
  ''' <summary>
  ''' Set up the FtpWebRequest for SSL, UseBinary, credentials, and proxy.
  ''' </summary>
  Private Shared Sub InitializeRequest(ByVal request As FtpWebRequest, ByVal uri As String, ByVal userName As String, ByVal password As String)
    request.UseBinary = True
    request.KeepAlive = False
    request.EnableSsl = uri.StartsWith("https")
 
    If userName.Trim().Length > 0 AndAlso password.Trim().Length > 0 Then
      request.Credentials = New NetworkCredential(userName, password)
    End If
 
    If WebProxy.GetDefaultProxy().Address IsNot Nothing Then
      Dim proxy As New WebProxy()
      proxy.UseDefaultCredentials = True
      proxy.Address = WebProxy.GetDefaultProxy().Address
      request.Proxy = proxy
    End If
  End Sub
 
  ''' <summary>
  ''' Find all the directories and files in the HTML response from the server.
  ''' </summary>
  Private Shared Function ParseAnchors(ByVal html As String) As List(Of FtpDirectoryEntry)
    Dim document As New mshtml.HTMLDocumentClass()
    TryCast(document, mshtml.IHTMLDocument2).write(html)
 
    Dim list As New List(Of FtpDirectoryEntry)()
    For Each element As mshtml.HTMLBRElement In document.getElementsByTagName("br")
 
      Dim sibling As Object = element.nextSibling
 
      Dim entry As FtpDirectoryEntry = Nothing
 
      While sibling IsNot Nothing
 
        If TypeOf sibling Is mshtml.IHTMLDOMTextNode Then
          Dim textNode As mshtml.IHTMLDOMNode = CType(sibling, mshtml.IHTMLDOMNode)
 
          entry = New FtpDirectoryEntry()
 
          ParseDirectoryEntry(entry, textNode.nodeValue)
          sibling = textNode.nextSibling
        ElseIf TypeOf sibling Is mshtml.HTMLAnchorElement Then
          Dim anchor As mshtml.HTMLAnchorElement = CType(sibling, mshtml.HTMLAnchorElement)
          entry.Name = anchor.innerText
          sibling = anchor.nextSibling
 
          list.Add(entry)
        End If
 
      End While
 
    Next element
    Return list
  End Function
 
  ''' <summary>
  ''' Parse the date/time and directory #text node text
  ''' </summary>
  ''' <example>
  ''' <![CDATA[02/08/05 12:00AM          <DIR>]]>
  ''' </example>
  Private Shared Sub ParseDirectoryEntry(ByVal entry As FtpDirectoryEntry, ByVal input As String)
    Dim pattern As String = "(?<timestamp>\d{1,2}/\d{1,2}/\d{2,4}\s+\d{1,2}:\d{1,2}\s?(AM|PM))\s+(?<dir>\<DIR\>)?"
    Dim match As Match = Regex.Match(input, pattern, RegexOptions.IgnoreCase)
    If match.Success Then
      Dim result As Date
      If Date.TryParse(match.Groups("timestamp").Value, result) Then
        entry.Timestamp = result
      End If
 
      If match.Groups("dir").Length > 0 Then
        entry.IsDirectory = True
      End If
    End If
  End Sub
 
End Class
 
Public Class FtpDirectoryEntry
  Public IsDirectory As Boolean
  Public Name As String
  Public Timestamp As DateTime
End Class
 
Advertisements
  1. #1 by Alyssa on June 22, 2008 - 6:45 pm

    Hi kelly, whats up? N2M here! I am bored~! unground me! the i won\’t be~! lol
     bye
    ~Alyssa~

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: