Build a Photo Viewer Using the New FTP Classes in .NET 2.0

ne of the features released with the 2.0 version of .NET was support for FTP. In .NET 2.0, you can now programmatically access FTP servers using the FtpWebRequest and FtpWebResponse managed classes (both derived from the WebRequest and WebResponse classes).

To illustrate the usefulness of using FTP in your .NET applications, I will build a Photo Viewer Windows application that accesses an FTP server. Using this application, users can upload photos to an FTP server and at the same time view images stored on the FTP server. This application is useful to companies who may need to access images uploaded by its partners. A good example is insurance companies, who may need to view photographs of car damages taken by workshop mechanics in order to estimate the cost of repair. Rather than build a complex Web application, the workshop and insurance companies can simply use this application to quickly upload and view photos.

Figure 1 shows what the application will look like when completed.

Creating the Application
Using Visual Studio 2005, create a new Windows application and name it PhotoViewer. Populate the default Form1 with the controls shown in Figure 2. The controls are:

  • Button
  • GroupBox
  • Label
  • PictureBox
  • TextBox
  • ToolStripStatusLabel
  • TreeView

The TreeView control is used to display the directory structure of the FTP server.


Figure 1. The completed Photo Viewer application.
?
Figure 2. Populate Form1 with the various controls shown.

Besides those listed above, you’ll also need to add an ImageList control to Form1 to contain three images representing an opened folder, a closed folder, and an image file. You can specify these images by specifying them in the control’s Image property (see Figure 3).

You also need to associate the ImageList control with the TreeView control by specifying ImageList1 in the ImageList property of the TreeView control (TreeView1).

Building the Directory Tree and Displaying Images
Switching to the code-behind of Form1, import the following namespaces:

Imports System.NetImports System.IO

Declare the following constants and member variables:

Public Class Form1    '---FTP server---    Const ftpServer As String = "ftp://127.0.0.1"    '---constants for the icon images---    Const icoOpen = 0    Const icoClose = 1    Const icoPhoto = 2    '---login credentials for the FTP server---    Private Username As String = "anonymous"    Private Password As String = "password"

When the form is loaded, display a node representing the root directory:

    Private Sub Form1_Load( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles MyBase.Load        Try            '?-create the root node for the TreeView?-            Dim node As New TreeNode            node.ImageIndex = icoClose            node.SelectedImageIndex = icoOpen            node.Text = "/"            '---add the root node to the control---            TreeView1.Nodes.Add(node)            '?-add the dummy child node to the root node?-            node.Nodes.Add("")            '---select the root node---            TreeView1.SelectedNode = node        Catch err As Exception            MsgBox(err.ToString)        End Try    End Sub

Note that I add a dummy node after each node is created. This is to ensure that the current node can be expanded to reveal subdirectories (even if there are none). This is shown in Figure 4.

Figure 3. Add three images to the ImageList control.

When a node is expanded (by clicking on the “+” symbol), the TreeView1_BeforeExpand event is called. You have to write code that checks to see if the current node is a leaf node (meaning it is not a directory, but a file). If it is a leaf node, exit the method. Otherwise you need to display its sub-directories (if any).

You should also change the current node icon to “open” if the node is selected and “closed” if the node is not selected. Below is the code for expanding folders and displaying the proper icon at each node:

    Private Sub TreeView1_BeforeExpand( _       ByVal sender As Object, _       ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) _       Handles TreeView1.BeforeExpand        '---if leaf node (photo) then exit---        If e.Node.ImageIndex = icoPhoto Then Return        '---remove the dummy node and display         ' the subdirectories and files---        Try            '---clears all the nodes and...---            e.Node.Nodes.Clear()            '---create the nodes again---            BuildDirectory(e.Node)        Catch err As Exception            ToolStripStatusLabel1.Text = err.ToString        End Try        '---change the icon for this node to open---        If e.Node.GetNodeCount(False) > 0 Then            e.Node.ImageIndex = icoClose            e.Node.SelectedImageIndex = icoOpen        End If    End Sub

The BuildDirectory() subroutine displays all the files and subdirectories within the current directory in the TreeView control. Before I look at the definition of the BuildDirectory() subroutine, I’ll define the GetDirectoryListing() function, whose main job it is to request from the FTP server the directory listing of a particular path:

    '---Get the file/dir listings and return them as a string array---    Private Function GetDirectoryListing(ByVal path As String) _       As String()        Try            Dim ftpReq As FtpWebRequest = WebRequest.Create(path)            ftpReq.Method = WebRequestMethods.Ftp.ListDirectoryDetails            ftpReq.Credentials = New NetworkCredential( _               Username, Password)            Dim FTPResp As FtpWebResponse = ftpReq.GetResponse            Dim ftpRespStream As Stream = FTPResp.GetResponseStream            Dim reader As StreamReader            reader = New StreamReader( _               ftpRespStream, System.Text.Encoding.UTF8)            '---obtain the result as a string array---            Dim result() As String = reader.ReadToEnd.Split(vbLf)            FTPResp.Close()            Return result        Catch ex As Exception            MsgBox(ex.ToString)            Return Nothing        End Try    End Function
Figure 4. Add a dummy node to a node so that it can be expanded.

To view the directory listing of an FTP server:

  • Create an instance of the FtpWebRequest class using the Create() method of the WebRequest class. The Create() method takes in a URI parameter (containing the full FTP path).
  • Set the command to be sent to the FTP server using the Method property of the FtpWebRequest class; in this case the command is ListDirectoryDetails.
  • Specify the login credential to the FTP server.
  • Obtain the response from the FTP server using the GetResponse() method from the FtpWebRequest class.
  • Retrieve the stream that contains response data sent from an FTP server using the GetResponseStream() method from the FtpWebResponse class.
  • You can use a StreamReader object to read the directory listing.

The directory listings are each separated by a LineFeed (vbLf) character. If your FTP server is configured with MS-DOS directory listing style (see Figure 5), the directory listing looks something like this:

12-11-06  10:54PM              2074750 DSC00098.JPG12-11-06  10:54PM              2109227 DSC00099.JPG12-11-06  10:49PM                 George12-11-06  10:49PM                 James12-11-06  10:58PM                 Wei-Meng Lee
Author’s Note: For this article, I am using the FTP service available in Windows XP. Also note that you need to give write permission to users so that they can create new directories and upload files to the FTP server.

As all subdirectories have the

field, you can simply differentiate subdirectories from files in the BuildDirectory() subroutine by looking for the “” words:

    '---Build the directory in the TreeView control---    Private Sub BuildDirectory(ByVal ParentNode As TreeNode)        Dim listing() As String = _           GetDirectoryListing(ftpServer & ParentNode.FullPath)        For Each line As String In listing            If line = String.Empty Then Exit For            Dim node As New TreeNode            If line.Substring(24, 5) = "" Then                '---this is a directory---                '---create a new node to be added---                With node                    .Text = line.Substring(39)                    .ImageIndex = icoClose                    .SelectedImageIndex = icoOpen                    '---add the dummy child node---                    .Nodes.Add("")                End With                ParentNode.Nodes.Add(node)            Else                '---this is a normal file---                '---create a new node to be added---                With node                    .Text = line.Substring(39)                    .ImageIndex = icoPhoto                    .SelectedImageIndex = icoPhoto                End With                ParentNode.Nodes.Add(node)            End If        Next    End Sub

When a node is selected, you first obtain the current path of the node and then display its path in the status bar if it is a folder. If it is an image node, download and display the photo using the DownloadImage() subroutine:

    Private Sub TreeView1_AfterSelect( _       ByVal sender As System.Object, _       ByVal e As System.Windows.Forms.TreeViewEventArgs) _       Handles TreeView1.AfterSelect        '---always ignore the first "/" char---        Dim FullPath As String = _           ftpServer & e.Node.FullPath.Substring(1).Replace(vbCr, "")        '---display the current folder selected---        If e.Node.ImageIndex <> icoPhoto Then            ToolStripStatusLabel1.Text = FullPath            Return        End If        '---download image---        DownloadImage(FullPath)    End Sub
Figure 5. Choose the directory listing style of the FTP server, in this case MS-DOS.

The DownloadImage() subroutine downloads an image from the FTP server and displays the image in a PictureBox control:

    '---Download the image from the FTP server---    Private Sub DownloadImage(ByVal path As String)        Try            Dim filename As String = path            Dim ftpReq As FtpWebRequest = WebRequest.Create(filename)            ftpReq.Method = WebRequestMethods.Ftp.DownloadFile            ftpReq.Credentials = New NetworkCredential( _               Username, Password)            ToolStripStatusLabel1.Text = "Downloading image..." & path            Application.DoEvents()            Dim FTPResp As FtpWebResponse = ftpReq.GetResponse            Dim ftpRespStream As Stream = FTPResp.GetResponseStream            PictureBox1.Image = Image.FromStream(ftpRespStream)            FTPResp.Close()            ToolStripStatusLabel1.Text = _               "Downloading image...complete (" & path & ")"        Catch ex As Exception            MsgBox(ex.Message)        End Try    End Sub

To download an image file using FTP and then bind it to a PictureBox control:

  • Create an instance of the FtpWebRequest class using the Create() method of the WebRequest class. The Create() method takes in a URI parameter (containing the path for the text file to be downloaded).
  • Set the command to be sent to the FTP server using the Method property of the FtpWebRequest class; in this case the command is DownloadFile.
  • Specify the login credential to the FTP server.
  • Obtain the response from the FTP server using the GetResponse() method from the FtpWebRequest class.
  • Retrieve the stream that contains response data sent from an FTP server using the GetResponseStream() method from the FtpWebResponse class.
  • Use the FromStream() method from the Image class to convert the response from the FTP server (containing the image) into an image.

Creating a New Directory
You can create a new directory on the FTP server by using the Create Folder button. To do so, select a current node to add the new folder, then:

  • Create an instance of the FtpWebRequest class using the Create() method of the WebRequest class. The Create() method takes in a URI parameter (containing the path of the new directory to create).
  • Set the command to be sent to the FTP server using the Method property of the FtpWebRequest class; in this case this command is MakeDirectory.
  • Specify the login credential to the FTP server.
  • Obtain the response from the FTP server using the GetResponse() method from the FtpWebRequest class.
    '---Create a new folder---    Private Sub btnCreateFolder_Click( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles btnCreateFolder.Click        '---ensure user selects a folder---        If TreeView1.SelectedNode.ImageIndex = icoPhoto Then            MsgBox("Please select a folder first.")            Exit Sub        End If        Try            '---formulate the full path for the folder             ' to be created---            Dim folder As String = ftpServer & _               TreeView1.SelectedNode.FullPath.Substring(1). _               Replace(vbCr, "") & "/" & txtNewFolderName.Text            Dim ftpReq As FtpWebRequest = WebRequest.Create(folder)            ftpReq.Method = WebRequestMethods.Ftp.MakeDirectory            ftpReq.Credentials = New NetworkCredential( _               Username, Password)            Dim ftpResp As FtpWebResponse = ftpReq.GetResponse            ToolStripStatusLabel1.Text = ftpResp.StatusDescription            ftpResp.Close()            '---refresh the newly added folder---            RefreshCurrentFolder()        Catch ex As Exception            MsgBox(ex.ToString)        End Try    End Sub

When a new folder is created, you need to update the TreeView control to reflect the newly added folder. This is accomplished by the RefreshCurrentFolder() subroutine:

    Private Sub RefreshCurrentFolder()        '---clears all the nodes and...---        TreeView1.SelectedNode.Nodes.Clear()        '---create the nodes again---        BuildDirectory(TreeView1.SelectedNode)    End Sub

Removing a Directory
To remove (delete) a directory, select the folder to delete and then:

  • Create an instance of the FtpWebRequest class using the Create() method of the WebRequest class. The Create() method takes in a URI parameter (containing the path of the new directory to remove).
  • Set the command to be sent to the FTP server using the Method property of the FtpWebRequest class; in this case the command is RemoveDirectory.
  • Specify the login credential to the FTP server.
  • Obtain the response from the FTP server using the GetResponse() method from the FtpWebRequest class.
    Private Sub btnRemoveFolder_Click( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles btnRemoveFolder.Click        If TreeView1.SelectedNode.ImageIndex = icoPhoto Then            MsgBox("Please select a folder to delete.")            Exit Sub        End If        Try            Dim FullPath As String = ftpServer & _               TreeView1.SelectedNode.FullPath. _               Substring(1).Replace(vbCr, "")            Dim ftpReq As FtpWebRequest = WebRequest.Create(FullPath)            ftpReq.Method = WebRequestMethods.Ftp.RemoveDirectory            ftpReq.Credentials = New NetworkCredential( _               Username, Password)            Dim ftpResp As FtpWebResponse = ftpReq.GetResponse            '---delete current node---            TreeView1.SelectedNode.Remove()            ToolStripStatusLabel1.Text = ftpResp.StatusDescription        Catch ex As Exception            MsgBox(ex.ToString)        End Try    End Sub

Note that if a directory is not empty (that is, it contains files and subdirectories), the deletion process will fail. You will need to remove its content first before removing the directory.

Uploading Photos
To upload photos to the FTP server, you first select a folder to upload the photos to, and then use an OpenFileDialog window to ask the user to select the photo(s) he wants to upload. Finally, you upload the photos individually using the UploadImage() subroutine (defined next):

    '---Upload Photos button---    Private Sub btnUploadPhotos_Click( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles btnUploadPhotos.Click        '---ensure user selects a folder---        If TreeView1.SelectedNode.ImageIndex = icoPhoto Then            MsgBox("Please select a folder to upload the photos.")            Exit Sub        End If        Dim openFileDialog1 As New OpenFileDialog()        With openFileDialog1            .Filter = "jpg files (*.jpg)|*.jpg"            .FilterIndex = 2            .RestoreDirectory = True            .Multiselect = True        End With        '---formulate the full path for the folder         ' to be created---        Dim currentSelectedPath As String = _           ftpServer & TreeView1.SelectedNode. _           FullPath.Substring(1). _           Replace(vbCr, "")        '---let user select the photos to upload---        If openFileDialog1.ShowDialog() = _           Windows.Forms.DialogResult.OK Then            '---upload each photo individually---            For i As Integer = 0 To _               openFileDialog1.FileNames.Length - 1                UploadImage(currentSelectedPath & "/" & _                   openFileDialog1.FileNames(i). _                   Substring(openFileDialog1.FileNames(i). _                   LastIndexOf("") + 1), _                   openFileDialog1.FileNames(i))            Next        End If        '---refresh the folder to show the uploaded photos---        RefreshCurrentFolder()    End Sub

The UploadImage() subroutine uploads a photo from the hard disk to the FTP server:

  • First, create a new instance of the WebClient class.
  • Specify the login credential to the FTP server
  • Upload the file to the FTP server using the UploadFile() method from the WebClient class. Note that you need to specify the full pathname of the file to be uploaded to the FTP server.
    '---upload a photo to the FTP server---    Private Sub UploadImage( _       ByVal path As String, ByVal filename As String)        Try            Dim client As New WebClient            client.Credentials = New NetworkCredential( _               Username, Password)            client.UploadFile(path, filename)            ToolStripStatusLabel1.Text = filename & " uploaded!"            Application.DoEvents()        Catch ex As Exception            MsgBox(ex.ToString)        End Try    End Sub

Deleting a Photo
To delete a photo, first select a photo to delete. Then:

  • Create an instance of the FtpWebRequest class using the Create() method of the WebRequest class. The Create() method takes in a URI parameter (containing the path for the file to be removed).
  • Set the command to be sent to the FTP server using the Method property of the FtpWebRequest class; in this case the command is DeleteFile.
  • Specify the login credential to the FTP server.
  • Obtain the response from the FTP server using the GetResponse() method from the FtpWebRequest class.
    Private Sub btnDeletePhoto_Click( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles btnDeletePhoto.Click        If TreeView1.SelectedNode.ImageIndex <> icoPhoto Then            MsgBox("Please select a photo to delete.")            Exit Sub        End If        Try            Dim FullPath As String = ftpServer & _               TreeView1.SelectedNode.FullPath. _               Substring(1).Replace(vbCr, "")            Dim ftpReq As FtpWebRequest = WebRequest.Create(FullPath)            ftpReq.Method = WebRequestMethods.Ftp.DeleteFile            ftpReq.Credentials = New NetworkCredential( _               Username, Password)            Dim ftpResp As FtpWebResponse = ftpReq.GetResponse            '---delete the current node---            TreeView1.SelectedNode.Remove()            ToolStripStatusLabel1.Text = ftpResp.StatusDescription        Catch ex As Exception            MsgBox(ex.ToString)        End Try    End Sub

Once the photo is removed from the FTP server, you also need to delete its node in the TreeView control.

That’s it! You can now test the application by pressing F5.

In this article, you have seen the usefulness of the two new managed classes in .NET 2.0: FtpWebRequest and FtpWebResponse. With some creativity, you can create useful applications using FTP. Let me know how you are using the new FTP class to simplify your application development.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

The Latest

microsoft careers

Top Careers at Microsoft

Microsoft has gained its position as one of the top companies in the world, and Microsoft careers are flourishing. This multinational company is efficiently developing popular software and computers with other consumer electronics. It is a dream come true for so many people to acquire a high paid, high-prestige job

your company's audio

4 Areas of Your Company Where Your Audio Really Matters

Your company probably relies on audio more than you realize. Whether you’re creating a spoken text message to a colleague or giving a speech, you want your audio to shine. Otherwise, you could cause avoidable friction points and potentially hurt your brand reputation. For example, let’s say you create a

chrome os developer mode

How to Turn on Chrome OS Developer Mode

Google’s Chrome OS is a popular operating system that is widely used on Chromebooks and other devices. While it is designed to be simple and user-friendly, there are times when users may want to access additional features and functionality. One way to do this is by turning on Chrome OS