Visual Basic 1002005 [A Developers Notebook] [Electronic resources]

شرکت رسانه او ریلی

نسخه متنی -صفحه : 97/ 91
نمايش فراداده

6.4. Upload and Download Files with FTP

Earlier versions of .NET didn't include any tools for FTP (File Transfer Protocol), a common protocol used to transfer files to and from a web server. As a result, you either had to purchase a third-party component or write your own (which was easy in principle but difficult to get right in practice).


Note: Need to upload files to an FTP site or download existing content? New support is available in VB 2005.


In .NET 2.0, a new FtpWebRequest class neatly fills the gap. However, the FtpWebRequest class has its own complexities, so Microsoft programmers simplified life for VB developers even further by extending the My.Computer.Network object to provide two quick access methods for completing basic FTP operations. These are UploadFile(), which sends a file to a remote server, and DownloadFile( ), which retrieves a file and stores it locally.

6.4.1. How do I do that?

Whether you use the FtpWebRequest class or the My.Computer.Network object, all FTP interaction in .NET is stateless. That means that you connect to the FTP site, perform a single operation (like transferring a file or retrieving a directory listing), and then disconnect. If you need to perform another operation, you need to reconnect. Fortunately, this process of connecting and logging in is handled automatically by the .NET Framework.

The easiest way to use FTP in a VB application is to do so through the My.Computer.Network object. If you use its FTP methods, you never need to worry about the tedious details of opening, closing, and reading streams. To download a file, the bare minimum information you need is the URL that points to the FTP site and the path that points to the local file. Here's an example:

My.Computer.Network.DownloadFile( _
"ftp:///pub/gnu/prep/gtk.README", "c:\readme.txt")

This command retrieves the file that is on the FTP site My.Computer.Network.UploadFile("c:\newfile.txt", _ "ftp:///pub/newfile.txt")

This command copies the local file newfile.txt from the directory c:\ to the FTP site , in the remote directory /pub.

Both DownloadFile( ) and UploadFile( ) support several overloads that take additional parameters, including credentials (the username and password information you might need to log on to a server) and a timeout parameter to set the maximum amount of time you'll wait for a response before giving up (the default is 1,000 milliseconds).

Unfortunately, the DownloadFile( ) and UploadFile( ) methods haven't been too robust in beta builds of Visual Basic 2005, and the methods may fail to work. An option that works better is the more sophisticated FtpWebRequest class. Not only does it perform more reliably, but it also fills a few glaring gaps in the FTP support provided by the My.Network.Computer. Because FtpWebRequest allows you to execute any FTP command, you can use it to retrieve directory listings, get file information, and more.


Note: Internet Explorer has its own built-in FTP browser. Just type a URL that points to an FTP site (like ftp://ftp.microsoft.com) into the IE address bar to browse what's there. You can use this tool to verify that your code is working correctly.


To use the FtpWebRequest class, you need to follow several steps. First, pass the URL that points to the FTP site to the shared WebRequest.Create( ) method:

Dim Request As FtpWebRequest 
Request = CType(WebRequest.Create("ftp://ftp.microsoft.com/MISC"), _
FtpWebRequest)

The WebRequest.Create() method examines the URL and returns the appropriate type of WebRequest object. Because FTP URLs always start with the scheme ftp://, the Create( ) method will return a new FtpWebRequest object.

Once you have the FtpWebRequest, you need to choose what FTP operation you want to perform by setting the FtpWebRequest.Method property with the text of the FTP command. Here's an example for retrieving directory information with the LIST command:

Request.Method = "LIST"

Once you've chosen the FTP operation you want to perform, the last step is to execute the command and read the response. The tricky part is the fact that the response is returned to you as a stream of text. It's up to you to move through this block of text line by line with a StreamReader and parse the information.

For example, the following code reads through a returned directory listing and displays each line in a Console window:

Dim Response As FtpWebResponse = CType(Request.GetResponse( ), FtpWebResponse)
Dim ResponseStream As Stream = Response.GetResponseStream( )
Dim Reader As New StreamReader(ResponseStream, System.Text.Encoding.UTF8)
Dim Line As String
Do
Line = Reader.ReadLine( )
Console.WriteLine(Line)
Loop Until Line = "

The output looks like this:

dr-xr-xr-x   1 owner    group               0 Jul  3  2002 beckyk
-r-xr-xr-x   1 owner    group           15749 Apr  8  1994 CBCP.TXT
dr-xr-xr-x   1 owner    group               0 Jul  3  2002 csformat
dr-xr-xr-x   1 owner    group               0 Aug  1  2002 DAILYKB
-r-xr-xr-x   1 owner    group             710 Apr 12  1993 DISCLAIM.TXT
dr-xr-xr-x   1 owner    group               0 Jul  3  2002 FDC
dr-xr-xr-x   1 owner    group               0 Jul  3  2002 friKB
dr-xr-xr-x   1 owner    group               0 Jul  3  2002 FULLKB
dr-xr-xr-x   1 owner    group               0 Jul  3  2002 Homenet
-r-xr-xr-x   1 owner    group              97 Sep 28  1993 INDEX.TXT
...

Clearly, if you want to manipulate individual pieces of information (like the file size) or distinguish files from directories, you'll need to do extra work to parse the text returned by the StreamReader.

Finally, when you're finished with the FTP request and response, you need to close the streams:

Reader.Close( )
Response.Close( )

To put it all in context, it helps to consider a simple FTP browsing application. Figure 6-1 shows a sample application that's included with the downloadable samples for this chapter.

Figure 6-1. A simple FTP Browser application

This Windows application includes the following controls:

A TextBox where you can enter a URL that points to a file or directory in an FTP site.

A Button named Query Directory that retrieves the folders and files at a given URL. This task requires the FtpWebRequest class.

A Button named Download File that downloads the file at a given URL. This task uses the My.Computer.Network.DownloadFile( ) method.

A FolderBrowserDialog that allows you to choose a folder where the downloaded file will be saved.

A ListView that shows the directory and file listing for the URL. This list is refreshed every time you click the Query Directory button. In addition, every time you click to select an item in the ListView, that information is automatically added to the URL in the text box. This allows you to quickly browse through an FTP site, drilling down several layers into the directory structure and selecting the file that interests you.

Example 6-4 shows code for the FTP browser form

Example 6-4. The FTP browser form
Public Class FtpForm
Inherits System.Windows.Forms.Form
' Stores the path currently shown in the ListView.
Private CurrentPath As String
Private Sub cmdQuery_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdQuery.Click
' Check the URI is valid.
Dim RequestUri As Uri = ValidateUri(txtFtpSite.Text)
If RequestUri Is Nothing Then Return
' Clear the ListView.
listDir.Items.Clear( )
' Create a new FTP request using the URI.
Dim Request As FtpWebRequest
Request = CType(WebRequest.Create(RequestUri), FtpWebRequest)
' Use this request for getting full directory details.
Request.Method = "LIST" 
Request.UsePassive = False
Dim Response As FtpWebResponse
Dim ResponseStream As Stream
Dim Reader As StreamReader
Try
' Execute the command and get the response.
Response = CType(Request.GetResponse( ), FtpWebResponse)
Debug.WriteLine("Status: " & Response.StatusDescription)
' Read the response one line at a time.
ResponseStream = Response.GetResponseStream( )
Reader = New StreamReader(ResponseStream, System.Text.Encoding.UTF8)
Dim Line As String
Do
Line = Reader.ReadLine( )
If Line <> " Then
Debug.WriteLine(Line)
' Extract just the file or directory name from the line.
Dim ListItem As New ListViewItem(Line.Substring(59).Trim( ))
If Line.Substring(0, 1) = "d" Then
ListItem.ImageKey = "Folder"
Else
ListItem.ImageKey = "File"
End If
listDir.Items.Add(ListItem)
End If
Loop Until Line = "
' Operation completed successfully. Store the current FTP path.
CurrentPath = RequestUri.ToString( )
Catch Ex As Exception
MessageBox.Show(Ex.Message)
Finally
' Clean up.
Reader.Close( )
Response.Close( )
End Try
End Sub
Private Sub cmdDownload_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdDownload.Click
' Check the URI is valid.
Dim RequestUri As Uri = ValidateUri(txtFtpSite.Text)
If RequestUri Is Nothing Then Return
' Prompt the user to choose a destination folder.
' Default the file name to the same file name used on the FTP server.
dlgSave.FileName = Path.GetFileName(txtFtpSite.Text)
If dlgSave.ShowDialog( ) <> Windows.Forms.DialogResult.OK Then
Return
End If
' Create a new FTP request using the URI.
Dim Request As FtpWebRequest
Request = CType(WebRequest.Create(RequestUri), FtpWebRequest)
' Use this request for downloading the file.
Request.UsePassive = False
Request.Method = "RETR"
Dim Response As FtpWebResponse
Dim ResponseStream, TargetStream As Stream
Dim Reader As StreamReader
Dim Writer As StreamWriter
Try
' Execute the command and get the response.
Response = CType(Request.GetResponse( ), FtpWebResponse)
Debug.WriteLine("Status: " & Response.StatusDescription)
Debug.WriteLine("File Size: " & Response.ContentLength)
' Create the destination file.
TargetStream = New FileStream(dlgSave.FileName, FileMode.Create)
Writer = New StreamWriter(TargetStream)
' Write the response to the file.
ResponseStream = Response.GetResponseStream( )
Reader = New StreamReader(ResponseStream, System.Text.Encoding.UTF8)
Writer.Write(Reader.ReadToEnd( ))
Catch Err As Exception
MessageBox.Show(Err.Message)
Finally
' Clean up.
Reader.Close( )
Response.Close( )
Writer.Close( )
End Try
End If
End Sub
Private Function ValidateUri(ByVal uriText As String) As Uri
Dim RequestUri As Uri
Try
' Check that the string is interpretable as a URI.
RequestUri = New Uri(uriText)
' Check that the URI starts with "ftp://"
If RequestUri.Scheme <> Uri.UriSchemeFtp Then
RequestUri = Nothing
End If
Catch
RequestUri = Nothing
End Try
If RequestUri Is Nothing Then
MessageBox.Show("Invalid Uri.")
Else
End If
Return RequestUri
End Function
Private Sub listDir_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles listDir.SelectedIndexChanged
' When a new item is selected in the list, add this 
' to the URI in the text box.
If listDir.SelectedItems.Count <> 0 Then
CurrentPath = CurrentPath.TrimEnd("/")
txtFtpSite.Text = CurrentPath & "/" & listDir.SelectedItems(0).Text
End If
End Sub
End Class

The most complex code found in this example occurs in the event handler for the cmdQuery button, which retrieves a directory listing, parses out the important information, and updates the ListView.

6.4.2. Where can I learn more?

In previous builds, the MSDN help included much more information on FTP access and different FTP operations under the index entry "FtpMethods," complete with useful demonstrations of the different methods. This entry has disappeared in recent builds (along with the FtpMethods class), but check for it to return. In the meantime, you can read up on the FTP protocol and supported commands at .