FTP Client

In this tutorial you will learn how to create an FTP Client, this is just a basic application to demonstrate the ability to use FTP in .NET, it uses the List View and Image List to display the files and their associated icons!

www.cespage.com/vb/vb08tut17.html

Step 1

Start Microsoft Visual Basic 2008 Express Edition, then select File then New Project... Choose Windows Forms Application from the New Project Window, enter a name for the Project and then click OK, see below:

New Project

Step 2

A Blank Form named Form1 should then appear, see below:

Form1

Step 3

With Form1 selected goto the Properties box and change the Name from Form1 to frmMain

Form1 Properties

Step 4

Then select Project then Add Class... and choose the "Class" Template if it is not already selected and give it the Name "FTP.vb" without the quotes, see below:

FTP Class

Step 5

With the empty FTP Class displayed, if not double click on the "FTP.vb" item in Solution Explorer, then enter the following above the Public Class FTP line:

Imports System.Net
Imports System.IO

Then enter the following below the Public Class FTP:

' Private Members

Private fRequest As FtpWebRequest
Private fHostname As String = ""
Private fUsername As String = ""
Private fPassword As String = ""
Private fLastDir As String = ""
Private fCurrentDir As String = ""

See Below:

FTP Class Imports and Declarations

Step 6

Again, with the FTP Class still displayed, enter the following Public Properties above "End Class" and below the "Private Members" section:

' Public Properties

''' <summary>Hostname</summary>
''' <remarks>ftp://ftp.example.com or ftp.example.com</remarks>
Public Property Hostname() As String
  Get
    If fHostname.StartsWith("ftp://") Then
      Return fHostname
    Else
      Return "ftp://" & fHostname
    End If
  End Get
  Set(ByVal Value As String)
      fHostname = Value
  End Set
End Property

''' <summary>Username</summary>
''' <remarks>If blank uses "anonymous" instead</remarks>
Public Property Username() As String
  Get
    Return IIf(fUsername = "", "anonymous", fUsername)
  End Get
  Set(ByVal Value As String)
    fUsername = Value
  End Set
End Property

''' <summary>Password</summary>
Public Property Password() As String
  Get
    Return fPassword
  End Get
  Set(ByVal Value As String)
    fPassword = Value
  End Set
End Property

''' <summary>Current Directory</summary>
''' <remarks>Return Directory ending with /</remarks>
Public Property CurrentDirectory() As String
  Get
    Return fCurrentDir & CStr(IIf(fCurrentDir.EndsWith("/"), "", "/"))
  End Get
  Set(ByVal Value As String)
    If Not Value.StartsWith("/") Then _
    Throw New ApplicationException("Directory should start with /")
    fCurrentDir = Value
  End Set
End Property

See Below:

FTP Public Properties

Step 7

Again, with the FTP Class still displayed, enter the following Private Methods above the "Public Properties" and below the "Private Members" section:

' Private Methods

''' <summary>Get FTP Login Credentials</summary>
''' <returns>Network Credential for FTP</returns>
Private Function GetCredentials() As Net.ICredentials
  Return New NetworkCredential(fUsername, fPassword)
End Function

''' <summary>Get FTP Request</summary>
''' <param name="URI">Host URI</param>
''' <returns>Result of FTP Request</returns>
Private Function GetRequest(ByVal URI As String) As FtpWebRequest
  Dim Result As FtpWebRequest = CType(FtpWebRequest.Create(URI), FtpWebRequest)
  Result.Credentials = GetCredentials()
  Result.KeepAlive = False
  Return Result
End Function

''' <summary>Get Response String</summary>
''' <param name="Request">Request for Response</param>
''' <returns>Get the result as string</returns>
Private Function GetResponseString(ByVal Request As FtpWebRequest) As String
  Dim Result As String
  Using Response As FtpWebResponse = CType(Request.GetResponse, FtpWebResponse)
    Dim Size As Long = Response.ContentLength
    Using DataStream As Stream = Response.GetResponseStream
      Using sReader As New StreamReader(DataStream)
        Result = sReader.ReadToEnd
        sReader.Close()
      End Using
      DataStream.Close()
    End Using
    Response.Close()
  End Using
  Return Result
End Function

''' <summary>Get the Size of an FTP Request</summary>
''' <param name="Request">FTP Request</param>
''' <returns>Request Data Length</returns>
Private Function GetRequestSize(ByVal Request As FtpWebRequest) As Long
  Dim lSize As Long
  Using Response As FtpWebResponse = CType(Request.GetResponse, FtpWebResponse)
    lSize = Response.ContentLength
    Response.Close()
  End Using
  Return lSize
End Function

''' <summary>Amend Path so it always starts with /</summary>
''' <param name="Path">Path to Amend</param>
''' <returns>Amended Path or orignal if not Amended</returns>
Private Function AmendPath(ByVal Path As String) As String
  Return CStr(IIf(Path.StartsWith("/"), "", "/")) & Path
End Function

''' <summary>Returns Full Path using Current Directory</summary>
''' <param name="File">File to Get Path From</param>
''' <returns>Full Path of File</returns>
Private Function GetFullPath(ByVal File As String) As String
  If File.Contains("/") Then
    Return AmendPath(File)
  Else
    Return CurrentDirectory & File
  End If
End Function

''' <summary>Get Directory</summary>
''' <param name="Directory">Directory to Get</param>
''' <returns>Directory Data</returns>
Private Function GetDirectory(ByVal Directory As String) As String
  If Directory = "" Then
    fLastDir = CurrentDirectory
    Return Hostname & CurrentDirectory
  Else
    If Not Directory.StartsWith("/") Then _
    Throw New ApplicationException("Directory should start with /")
    fLastDir = Directory
    Return Hostname & Directory
  End If
End Function

See Below:

FTP Private Methods

Step 8

Finally in the FTP Class, enter the following Public Methods above the "Public Properties" and below the "Private Methods" Section:

' Public Methods

''' <summary>Connection</summary>
''' <returns>Returns True if Connection established, False if not</returns>
Public Function Connection() As Boolean
  If fHostname <> "" And (fUsername <> "" Or fPassword <> "") Then
    fRequest = GetRequest(Hostname)
    fRequest.Method = WebRequestMethods.Ftp.PrintWorkingDirectory
    Try
        GetResponseString(fRequest) ' Get but Ignore Response
      Return True
    Catch ex As Exception
      Return False
    End Try
  Else
    Return False
  End If
End Function

''' <summary>List Directory</summary>
''' <param name="Directory">Directory to List (Optional)</param>
''' <returns>A list of Files and Foldoers as a List(of String)</returns>
Public Function DirectoryList(Optional ByVal Directory As String = "") As List(Of String)
  Dim Result As String
  Dim lsResult As New List(Of String)
  fRequest = GetRequest(GetDirectory(Directory))
  fRequest.Method = WebRequestMethods.Ftp.ListDirectory ' Simple List
  Result = GetResponseString(fRequest) ' Get Result String
  Result = Result.Replace(vbCrLf, vbCr).TrimEnd(Chr(13))
  lsResult.AddRange(Result.Split(Chr(13))) ' Split String into List
  CurrentDirectory = Directory
  Return lsResult
End Function

''' <summary>Rename Directory</summary>
''' <param name="SourcePath">Directory to Rename</param>
''' <param name="TargetDirectory">New Directory Name</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function DirectoryRename(ByVal SourcePath As String, _
                              ByVal TargetDirectory As String) As Boolean
  Dim Source As String = Hostname & AmendPath(SourcePath)
  Dim Target As String = AmendPath(TargetDirectory)
  fRequest = GetRequest(Source)
  fRequest.Method = WebRequestMethods.Ftp.Rename
  fRequest.RenameTo = TargetDirectory
  Try
    GetResponseString(fRequest) ' Get but Ignore Response
    Return True
  Catch ex As Exception
    Return False
  End Try
End Function

''' <summary>Create Directory</summary>
''' <param name="Path">Directory to Create</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function DirectoryCreate(ByVal Path As String) As Boolean
  Dim URI As String = Hostname & CurrentDirectory & AmendPath(Path)
  fRequest = GetRequest(URI)
  fRequest.Method = WebRequestMethods.Ftp.MakeDirectory
  Try
    GetResponseString(fRequest) ' Get but Ignore Response
    Return True
  Catch ex As Exception
    Return False
  End Try
End Function

''' <summary>Delete Directory</summary>
''' <param name="Path">Directory to Delete</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function DirectoryDelete(ByVal Path As String) As Boolean
  Dim URI As String = Hostname & CurrentDirectory & AmendPath(Path)
  fRequest = GetRequest(URI)
  fRequest.Method = WebRequestMethods.Ftp.RemoveDirectory
  Try
    GetResponseString(fRequest) ' Get but Ignore Response
    Return True
  Catch ex As Exception
    Return False
  End Try
End Function

''' <summary>Determine Size of Remote File</summary>
''' <param name="Filename">Filename of File</param>
''' <returns>Size of File as Long</returns>
Public Function FileSize(ByVal Filename As String) As Long
  Dim Path, URI As String
  If Filename.Contains("/") Then
    Path = AmendPath(Filename)
  Else
    Path = CurrentDirectory & Filename
  End If
  URI = Hostname & Path
  fRequest = GetRequest(URI)
  fRequest.Method = WebRequestMethods.Ftp.GetFileSize
  GetResponseString(fRequest) ' Get but Ignore Response
  Return GetRequestSize(fRequest)
End Function

''' <summary>Determine of Remote File Exists</summary>
''' <param name="Filename">Filename of File</param>
''' <returns>True if Exists, False if Not</returns>
Public Function FileExists(ByVal Filename As String) As Boolean
  Dim lSize As Long
  Try
    lSize = FileSize(Filename)
    Return True
  Catch ex As Exception ' Handle Request not Found Only
    If TypeOf (ex) Is System.Net.WebException Then
      If ex.Message.Contains("550") Then
        Return False ' No File
      Else
        Throw
      End If
    Else
      Throw
    End If
  End Try
End Function

''' <summary>Rename Remote File</summary>
''' <param name="SourceFilename">File to Rename</param>
''' <param name="TargetFilename">New Name for File</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function FileRename(ByRef SourceFilename As String, _
                         ByVal TargetFilename As String) As Boolean
  Dim Source, Target, URI As String
  Source = GetFullPath(SourceFilename)
  If Not FileExists(Source) Then
    Throw New FileNotFoundException("File " & Source & " not found")
  End If
  Target = GetFullPath(TargetFilename)
  If Target = Source Then
    Throw New ApplicationException("Source and Target Filenames are the Same")
  ElseIf FileExists(Target) Then
    Throw New ApplicationException("Target File " & Target & " already exists")
  End If
  URI = Hostname & Source
  fRequest = GetRequest(URI)
  fRequest.Method = WebRequestMethods.Ftp.Rename
  fRequest.RenameTo = Target
  Try
    GetResponseString(fRequest) ' Get but Ignore Response
    Return True
  Catch ex As Exception
    Return False
  End Try
End Function

''' <summary>Delete Remote File</summary>
''' <param name="Filename">File do Delete</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function FileDelete(ByVal Filename As String) As Boolean
  Dim URI As String
  URI = Hostname & GetFullPath(Filename)
  fRequest = GetRequest(URI)
  fRequest.Method = WebRequestMethods.Ftp.DeleteFile
  Try
    GetResponseString(fRequest) ' Get but Ignore Response
    Return True
  Catch ex As Exception
    Return False
  End Try
End Function

''' <summary>Upload Local File to FTP Server</summary>
''' <param name="LocalFileInfo">Local File Info</param>
''' <param name="RemoteFilename">Target Filename (Optional)</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function Upload(ByVal LocalFileInfo As FileInfo, _
                     Optional ByVal RemoteFilename As String = "") As Boolean
  Dim Remote, URI As String
  Dim DataRead As Integer
  If RemoteFilename.Trim = "" Then ' If No RemoteFileInfo Use LocalFileInfo
    Remote = CurrentDirectory & LocalFileInfo.Name
  ElseIf RemoteFilename.Contains("/") Then
    Remote = AmendPath(RemoteFilename) ' If has / then is Full Path
  Else ' Otherwise is filename only use the Current Directory for Path
    Remote = CurrentDirectory & RemoteFilename
  End If
  URI = Hostname & Remote
  fRequest = GetRequest(URI)
  fRequest.Method = Net.WebRequestMethods.Ftp.UploadFile ' File Upload
  fRequest.UseBinary = True ' Binary Mode
  fRequest.ContentLength = LocalFileInfo.Length ' Notify FTP of Expected Size
  Dim Content(2047) As Byte ' Byte Buffer Store, at least 1 Byte
  Using LocalData As FileStream = LocalFileInfo.OpenRead() ' Read File
    Try ' Open File Stream, Upload Data
      Using UploadData As Stream = fRequest.GetRequestStream
        Do
          DataRead = LocalData.Read(Content, 0, 2048)
          UploadData.Write(Content, 0, DataRead)
        Loop Until DataRead < 2048
        UploadData.Close()
      End Using
    Catch ex As Exception
      ' Do Nothing on Exception
    Finally
      LocalData.Close() ' Close File Stream
    End Try
  End Using
  Return True
End Function

''' <summary>Upload Local File to FTP Server</summary>
''' <param name="LocalFilename">Local File</param>
''' <param name="RemoteFilename">Target Filename (Optional)</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function Upload(ByVal LocalFilename As String, _
                     Optional ByVal RemoteFilename As String = "") As Boolean
  If Not File.Exists(LocalFilename) Then ' Check Local File Exists
    Throw New ApplicationException("File " & LocalFilename & " not found")
  End If
  Return Upload(New FileInfo(LocalFilename), RemoteFilename)
End Function

''' <summary>Download Remote File to Local</summary>
''' <param name="RemoteFilename">Remote Filename, if Required</param>
''' <param name="LocalFileInfo">Local File Information</param>
''' <param name="PermitOverwrite">Overwrite Local File if it Exists</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function Download(ByVal RemoteFilename As String, _
                       ByVal LocalFileInfo As FileInfo, _
                       Optional ByVal PermitOverwrite As Boolean = False)
  If LocalFileInfo.Exists And Not PermitOverwrite Then _
  Throw New ApplicationException("Local file already exists")
  Dim Remote, URI As String
  Dim DataRead As Integer
  If RemoteFilename.Trim = "" Then
    Throw New ApplicationException("File not specified")
  ElseIf RemoteFilename.Contains("/") Then
    Remote = AmendPath(RemoteFilename)
  Else
    Remote = CurrentDirectory & RemoteFilename
  End If
  URI = Hostname & Remote
  fRequest = GetRequest(URI)
  fRequest.Method = WebRequestMethods.Ftp.DownloadFile
  fRequest.UseBinary = True
  Using Response As FtpWebResponse = CType(fRequest.GetResponse, FtpWebResponse)
    Using ResponseStream As Stream = Response.GetResponseStream
      Using DownloadData As FileStream = LocalFileInfo.OpenWrite
        Try
          Dim Buffer(2048) As Byte
          Do
            DataRead = ResponseStream.Read(Buffer, 0, Buffer.Length)
            DownloadData.Write(Buffer, 0, DataRead)
          Loop Until DataRead = 0
          ResponseStream.Close()
          DownloadData.Flush()
          DownloadData.Close()
        Catch ex As Exception
          DownloadData.Close()
          LocalFileInfo.Delete() ' Delete Partial Data Downloads
          Throw
        End Try
      End Using
      ResponseStream.Close()
    End Using
    Response.Close()
  End Using
  Return True
End Function

''' <summary>Download Remote File to Local</summary>
''' <param name="RemoteFilename">Remote Filename, if Required</param>
''' <param name="LocalFilename">Full Path of Local File</param>
''' <param name="PermitOverwrite">Overwrite Local File if it Exists</param>
''' <returns>True if Success, False if Error/Fail</returns>
Public Function Download(ByVal RemoteFilename As String, _
                       ByVal LocalFilename As String, _
                       Optional ByVal PermitOverwrite As Boolean = False) As Boolean
  Return Me.Download(RemoteFilename, New FileInfo(LocalFilename), PermitOverwrite)
End Function

See Below:

FTP Public Methods

Step 9

Select frmMain, by double-clicking on the entry for "frmMain in Solution Explorer or click on the "frmMain [Design]" Tab if Present.
Then from the Components tab on the Toolbox select the ImageList component:

ImageList Component

Step 10

Draw am ImageList on the Form, or double-click on the ImageList entry in the Toolbox, and it will appear in the pane, beneath the form, see below:

ImageList in Pane below frmMain

Step 11

Then goto the Properties box and change the Name to "ExplorerIcons", ColorDepth to "Depth32Bit", and ImageSize to "32,32", all without quotes, see Below:

ImageList Properties

Step 12

Then from the Common Controls tab on the Toolbox select the ListView component:

ListView Component

Step 13

Draw a ListView on the Form, see below:

frmMain with ListView

Step 14

Then goto the Properties box and change the Name to "Explorer", Dock property to "Fill", LargeImageList to "ExplorerIcons" and View to "LargeIcon", all without quotes, see Below:

Explorer Properties

Step 15

Then from the Menus & Toolbars tab on the Toolbox select the MenuStrip Control, see Below:

MenuStrip Component

Step 16

Either double-click on the MenuStrip Control entry in the Menu & Toolbars tab on the Toolbox or keep the MenuStrip Component Clicked and then move it over the Form then let go. Change the Name of the MenuStrip in the properties to mnuFTP. The Form will then look as below:

frmMain with MenuStrip

Step 17

Click or select where the MenuStrip says "Type Here", an editable Textbox will appear type in "File" without the quotes in this Box, then in the Box below that type in "Connect...", then "-" which is minus or the hyphen key which will appear as a Seperator, then below that type "Upload...", then "Download...", then another "-" for a seperator, and then finally "Exit". The MenuStrip should look as below:

mnuFTP with SubMenus

Step 18

Click or select where the MenuStrip says "Type Here" next to "File", and in this type in "Edit" without the quotes in this Box, then in the Box below that type "New Folder...", then type in "-" which is minus or the hyphen key for a Seperator, then below that "Rename..." and finally "Delete". The MenuStrip should look as below:

mnuFTP with Edit Sub Menu Items

Step 19

Right Click on the Form or the entry of the Form in Solution Explorer and choose the "View Code" option then above the "Public Class frmMain" type the following:

Imports System.Runtime.InteropServices

Then below "Public Class frmMain" enter the following Private Declarations and API Functions:

Private Const PASSWORD_TITLE As String = "Password:"
Private Const ASTERISK_KEYCODE = 42
Private Const GW_CHILD = 5
Private Const WM_CREATE = &H1
Private Const EM_SETPASSWORDCHAR = &HCC
Private WindowHandle As Integer
Private Client As New FTP

<DllImport("shell32.dll", CallingConvention:=CallingConvention.Cdecl)> _
Private Shared Function ExtractIcon(ByVal hIcon As IntPtr, _
ByVal lpszExeFileName As String, ByVal nIconIndex As Integer) As IntPtr
End Function

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

Private Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Integer, ByVal wCmd As Integer) As Integer

Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, _
 ByVal lParam As Integer) As Integer

See Below:

FTP Client Declaration

Step 20

While still in the Code View for frmMain, enter the following above the "End Class" of "Public Class frmMain":

Private Sub Password()
  Dim InputWindow As Integer
  InputWindow = GetWindow(WindowHandle, GW_CHILD)
  SendMessage(InputWindow, EM_SETPASSWORDCHAR, ASTERISK_KEYCODE, 0)
End Sub

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
  MyBase.WndProc(m)
  If m.Result.ToInt32 = WM_CREATE Then
    WindowHandle = FindWindow(vbNullString, PASSWORD_TITLE)
  ElseIf WindowHandle > 0 Then
    Password()
    WindowHandle = 0
  End If
End Sub

Private Function GetIcon(ByVal Filename As String, ByRef ImageList As ImageList) As Integer
  Dim sIcon, sExt As String
  Dim iIcon As Integer
  Dim hIcon As IntPtr
  If Not Filename.Contains(".") Then ' Folder, Get Folder Icon
    hIcon = ExtractIcon(IntPtr.Zero, "Shell32.dll", 3)
    ImageList.Images.Add(Icon.FromHandle(hIcon))
  Else ' File, Get Associated Icon
    sExt = New IO.FileInfo(Filename).Extension
    sIcon = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(sExt).GetValue("")
    sIcon = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(sIcon).OpenSubKey("DefaultIcon").GetValue("")
    If sIcon.Contains(",") Then
      iIcon = sIcon.Split(",")(1)
      sIcon = sIcon.Split(",")(0)
      hIcon = ExtractIcon(IntPtr.Zero, sIcon, iIcon)
      ImageList.Images.Add(Icon.FromHandle(hIcon))
    Else ' No Icon Found for File Type
      hIcon = ExtractIcon(IntPtr.Zero, "Shell32.dll", 1)
      ImageList.Images.Add(Icon.FromHandle(hIcon))
    End If
  End If
  Return ImageList.Images.Count - 1
End Function

Private Function GetParent(ByVal Path As String)
  Dim strPath As String
  If Path.EndsWith("/") Then
    strPath = Mid(Path, 1, Path.LastIndexOf("/"))
  Else
    strPath = Path
  End If
  strPath = strPath.Substring(0, strPath.LastIndexOf("/"))
  If strPath = "" Then
    strPath = "/"
  End If
  Return strPath
End Function

Private Sub Directory(Optional ByVal Current As String = "/")
  Dim Path As String
  Dim Result As List(Of String)
  Result = Client.DirectoryList(Current)
  ExplorerIcons.Images.Clear()
  Explorer.Items.Clear()
  If Current <> "/" Then
    Dim Up As New ListViewItem
    Up.Tag = GetParent(Client.CurrentDirectory)
    Up.Text = "..."
    Up.ImageIndex = GetIcon("parent", ExplorerIcons)
    Explorer.Items.Add(Up)
  End If
  For Each Line As String In Result
    If Line <> "" Then
      Dim Item As New ListViewItem
      Item.Tag = Line ' Full Name
      Path = Current.Replace("/", "") & "/"
      If Line.Contains(Path) Then
          Line = Replace(Line, Path, "")
      End If
      Item.Text = Line ' Partial Name
      Item.ImageIndex = GetIcon(Line, ExplorerIcons)
      Explorer.Items.Add(Item)
    End If
  Next
End Sub

Private Sub Download(ByVal Location As String)
  Dim Download As New SaveFileDialog
  Download.AddExtension = True
  Download.DefaultExt = IO.Path.GetExtension(Location)
  Download.CheckPathExists = True
  Download.Filter = UCase(Download.DefaultExt) & _
  " File (*." & Download.DefaultExt & ")|*." & Download.DefaultExt
  Download.FileName = Location
  If Download.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
    Try
      Client.Download(Location, Download.FileName)
    Catch ex As Exception
      ' Do nothing on Exception
    End Try
  End If
End Sub

See Below:

FTP Client Functions

Step 21

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Connect..." (ConnectToolStripMenuItem) and type the following in the ConnectToolStripMenuItem_Click() Sub:

Client.Hostname = InputBox("Hostname:", "Host Name")
Client.Username = InputBox("Username:", "User Name")
Client.Password = InputBox("Password:", PASSWORD_TITLE)
Directory()

See Below:

File Menu Connect Menu Item Click Event

Step 22

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Upload..." (UploadToolStripMenuItem) and type the following in the UploadToolStripMenuItem_Click() Sub:

If Client.Connection Then
  Dim Upload As New OpenFileDialog()
  Upload.Filter = "All files (*.*)|*.*"
  Upload.CheckFileExists = True
  If Upload.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
    Try
      Client.Upload(Upload.FileName)
      Directory(Client.CurrentDirectory)
    Catch ex As Exception
      ' Do nothing on Exception
    End Try
  End If
Else
  MsgBox("Please connect to FTP Server", _
  MsgBoxStyle.Exclamation, "FTP Client")
End If

See Below:

File Menu Upload Menu Item Click Event

Step 23

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Download..." (DownloadToolStripMenuItem) and type the following in the DownloadToolStripMenuItem_Click() Sub:

If Client.Connection Then
  Dim Selected As ListViewItem
  If Explorer.SelectedItems.Count > 0 Then
    Selected = Explorer.Items(Explorer.SelectedItems(0).Index)
    If Selected.Tag.Contains(".") Then ' File
      Download(Selected.Tag)
    End If
  End If
Else
  MsgBox("Please connect to FTP Server", _
  MsgBoxStyle.Exclamation, "FTP Client")
End If

See Below:

File Menu Download Menu Item Click Event

Step 24

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Exit" (ExitToolStripMenuItem) and type the following in the ExitToolStripMenuItem_Click() Sub

Dim Response As MsgBoxResult
Response = MsgBox("Are you sure you want to Exit FTP Client?", _
                  MsgBoxStyle.Question + MsgBoxStyle.YesNo, _
                  "FTP Client)
If Response = MsgBoxResult.Yes Then
  End
End If

See Below:

File Menu Exit Menu Item Click Event

Step 25

Click on the [Design] Tab to view the form again, then Click on "Edit" on the MenuStrip, then Double Click on the Menu Item Labeled "New Folder..." (NewFolderToolStripMenuItem) and type the following in the NewFolderToolStripMenuItem_Click() Sub:

If Client.Connection Then
  Dim Response As String = ""
  Response = InputBox("Folder Name:", "FTP Client", Response)
  If Response <> "" Then
      Client.DirectoryCreate(Response)
      Directory(Client.CurrentDirectory)
  End If
Else
  MsgBox("Please connect to FTP Server", _
  MsgBoxStyle.Exclamation, "FTP Client")
End If

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Edit", then Double Click on the Menu Item Labeled "Rename..." (RenameToolStripMenuItem) and type the following in the RenameToolStripMenuItem_Click() Sub:

If Client.Connection Then
  Dim Response As String
  Dim Selected As ListViewItem
  If Explorer.SelectedItems.Count > 0 Then
    Selected = Explorer.Items(Explorer.SelectedItems(0).Index)
    Response = InputBox("Name:", "FTP Client", Selected.Text)
    If Response <> "" Then
      Try
        If Selected.Tag.Contains(".") Then ' File
          Client.FileRename(Selected.Tag, Response)
        Else ' Folder
          Client.DirectoryRename(Selected.Tag, Response)
        End If
      Catch ex As Exception
        ' Do nothing on Exception
      End Try
      Directory()
	  End If
  End If
Else
  MsgBox("Please connect to FTP Server", _
  MsgBoxStyle.Exclamation, "FTP Client")
End If

Click on the [Design] Tab to view the form again, then Click on "Edit" on the MenuStrip, then Double Click on the Menu Item Labeled "Delete" (DeleteToolStripMenuItem) and type the following in the DeleteToolStripMenuItem_Click() Sub:

If Client.Connection Then
  Dim Selected As ListViewItem
  If Explorer.SelectedItems.Count > 0 Then
    Selected = Explorer.Items(Explorer.SelectedItems(0).Index)
    Try
      If Selected.Tag.Contains(".") Then ' File
        Client.FileDelete(Selected.Tag)
      Else ' Folder
        Client.DirectoryDelete(Selected.Tag)
      End If
    Catch ex As Exception
      ' Do nothing on Exception
    End Try
    Directory()
  End If
Else
  MsgBox("Please connect to FTP Server", _
  MsgBoxStyle.Exclamation, "FTP Client")
End If

See Below:

Edit Menu Events

Step 26

Click on the [Design] Tab to view the form again, then Double Click on the Form (frmMain) and type the following in the frmMain_Load() Sub

Me.Text = "FTP Client"

See Below:

frmMain Load Event

Step 27

Return to the Code View, by double-clicking on the Form, this will show the frmMain_Load Sub from the previous step, in Code view are two drop-down boxes, select "Explorer" from the first drop-down with "(frmMain Events)", and then from the other "(Declarations)" select "DoubleClick" and type the following in the Explorer_DoubleClick(...) Sub:

If Client.Connection Then
  Dim Selected As ListViewItem
  If Explorer.SelectedItems.Count > 0 Then
    Selected = Explorer.Items(Explorer.SelectedItems(0).Index)
    If Selected.Tag.Contains(".") Then ' File
      Download(Selected.Tag)
    Else ' Folder
      If Selected.Tag.StartsWith("/") Then
        Directory(Selected.Tag) ' List
      Else
        Directory("/" & Selected.Tag) ' List
      End If
    End If
  End If
Else
  MsgBox("Please connect to FTP Server", _
  MsgBoxStyle.Exclamation, "FTP Client")
End If

See Below:

FTP Client Explorer DoubleClick Event

Step 28

Steps 28-30 are optional and just add Keyboard Shortcuts to the MenuItems, you don't have to do these if you don't want to!
Click on the [Design] Tab to view the form again, click on "Connect..." on the MenuStrip then in the Properties box look for the "ShortcutKeys" option and click on the Drop Down arrow where "None" appears. Check the "Ctrl" Checkbox in "Modifiers" and then in the "Key" dropdown list select "O", see below:

File Menu Connect Menu Item Shortcut Key

Step 29

Set "Upload..." to "Ctrl+U" and "Download..." to "Ctrl+D", The File Menu should appear as below:

File Menu with Shortcut Keys

Step 30

Click on or select the "Edit" Menu and set the "ShortcutKeys" Properties for the following Menu Items, "New Folder..." should be set to "Ctrl+Ins", "Rename" to "F2", finally "Delete" should be "Del". The Edit Menu should appear as below:

Edit Menu with Shortcut Keys

Step 31

Save the Project as you have now finished the application, then click on Start:

Start

When you do the following will appear:

FTP Client Running

Step 32

Use the Connect feature to Connect to an FTP site, by entering th Hostname (FTP Address), Username and Password (shows as Asterisks), see below:

FTP Client

Step 33

Click File then Exit or click on the Close button Close on the top right to end the application.

This FTP Client is vert basic, it is recommended that it only be used for demonstration purposes and to learn from, you may wish to use it with an FTP Server on your own Computer search online for "free FTP server" and look for one that you can connect to. Make improvements to the client so it checks before Deleting, and make it your own!