Downloading Text FTP Data

Now that we've reviewed FTP methods in Visual Basic, let's put them to work. Our goal in our example program, FTPer, is to download the directory of ftp.microsoft.com, indicate which text files are available, and let the user download the selected one:

This example is not very fancy, so the Internet Transfer control OpenURL() method will work best here. Using this method, you can fetch files with the HTTP and FTP protocols. That's all it does—if you want to use commands such as DIR or PUT, you must use the Execute method.

Now that we've added an Internet Transfer control to our FTPer project, we can put it to work. When the program starts, we'll have it automatically connect to ftp.microsoft.com and display a directory listing of the text files there (the files with the extension .txt). We will use the Form_Load() event handler, which is called when the main form is first displayed; currently it looks like this (where the program positions the form on the screen and sizes it):

Private Sub Form_Load()
    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
End Sub

Next, we get the directory of the Microsoft server ftp.microsoft.com. We use the OpenURL() method, loading the directory information into a string named DirectoryText:

Private Sub Form_Load()
—> Dim DirectoryText
    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
—> DirectoryText = Inet1.OpenURL("ftp://ftp.microsoft.com")
        .
        .
        .

Because we have not specified a file to download, we will get a listing of ftp.microsoft.com's directory. In general, the OpenURL() method has two arguments: the URL you want to get and a data type setting, which can hold the values icString (= 0, the default) to retrieve the data as a string, or icByteArray (= 1) to retrieve the data as a byte array. Although we skipped the second parameter, we could also have written that line this way:

DirectoryText = Inet1.OpenURL("ftp://ftp.microsoft.com", icString)

When the program executes this line, it connects to the Internet (assuming that the user has a connection set up for the Internet) if the computer is not already connected and logs in to ftp.microsoft.com. Then it gets the directory of ftp.microsoft.com and places it into the string DirectoryString. With the addition of the Inet1 control to our program and the use of the OpenURL() method, we've connected to the Internet using the FTP protocol.

We can get the length of the directory data by checking the length of the string DirectoryString:

Private Sub Form_Load()
    Dim DirectoryText
    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
    DirectoryText = Inet1.OpenURL("ftp://ftp.microsoft.com")
—> DirectoryTextLength = Len(DirectoryText)
        .
        .
        .
End Sub

Here's the actual data we would receive for the directory of ftp.microsoft.com; note that it is set up in HTML to make it easy for Web browsers:

<BODY>
  <H2>FTP root at ftp.microsoft.com</H2>
    <HR>
    <H4><PRE>
    This is FTP.MICROSOFT.COM.  Please see the
    dirmap.txt file for more information.
    </PRE></H4>
    <HR>
    <PRE>
    09/20/96 07:34PM      Directory <A HREF="/bussys/"><B>bussys</B></A>
    09/23/96 08:46PM      Directory <A HREF="/deskapps/"><B>deskapps</B></A>
    08/16/96 05:33PM      Directory <A HREF="/developr/"><B>developr</B></A>
    09/11/96 01:01AM          8,012 <A HREF="/dirmap.htm">dirmap.htm</A>
    09/11/96 12:57AM          4,368 <A HREF="/dirmap.txt">dirmap.txt</A>
    08/25/94 12:00AM            712 <A HREF="/disclaimer.txt">disclaimer.txt</A>
    11/19/96 01:23AM      Directory <A HREF="/KBHelp/"><B>KBHelp</B></A>
    12/03/96 11:10AM      8,168,053 <A HREF="/ls-lR.txt">ls-lR.txt</A>
    12/03/96 11:10AM      1,065,823 <A HREF="/ls-lR.Z">ls-lR.Z</A>
    12/03/96 11:10AM        879,116 <A HREF="/LS-LR.ZIP">LS-LR.ZIP</A>
    10/20/95 12:00AM      Directory <A HREF="/MSCorp/"><B>MSCorp</B></A>
    10/27/96 12:24AM      Directory <A HREF="/msdownload/"><B>msdownload</B></A>
    10/11/95 12:00AM      Directory <A HREF="/peropsys/"><B>peropsys</B></A>
    11/30/95 12:00AM      Directory <A HREF="/Products/"><B>Products</B></A>
    10/28/96 11:47PM      Directory <A HREF="/Services/"><B>Services</B></A>
    05/30/96 01:39AM      Directory <A HREF="/Softlib/"><B>Softlib</B></A>
    04/08/96 02:21PM      Directory <A HREF="/solutions/"><B>solutions</B></A>
    </PRE>
    <HR>
</BODY>
</HTML>

We want to place the names of the text files into the listbox List1, so we will write our program to search through the listing for .txt files; we do that by searching for ".txt," which locates the end of the file name strings that we want. We will place each file name into its own string, so we call the location of the substring ".txt" StringEnd (the end of the file name string):

Private Sub Form_Load()
    Dim DirectoryText
    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
    DirectoryText = Inet1.OpenURL("ftp://ftp.microsoft.com")
    DirectoryTextLength = Len(DirectoryText)
—> StringEnd = InStr(DirectoryText, ".txt""")
        .
        .
        .
End Sub

As long as the variable StringEnd is not 0, we have found a match. We should set up a loop, because there will be more than one text file to find:

Private Sub Form_Load()
    Dim DirectoryText
    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
    DirectoryText = Inet1.OpenURL("ftp://ftp.microsoft.com")
    DirectoryTextLength = Len(DirectoryText)
    StringEnd = InStr(DirectoryText, ".txt""")
—> While (StringEnd <> 0)
      .
      .
      .
—> Wend
End Sub

Because the directory of ftp.microsoft.com is set up as a Web page (which is quite common), each file name is enclosed in quotation marks:

09/11/96 12:57AM          4,368 <A HREF="/dirmap.txt">dirmap.txt</A>

Now that we've found the ".txt" part of the file name, we can work back to the quotation mark to get the whole file name and the length of the file name (which we place in the variable StringLength):

Private Sub Form_Load()
    Dim DirectoryText
    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
    DirectoryText = Inet1.OpenURL("ftp://ftp.microsoft.com")
    DirectoryTextLength = Len(DirectoryText)
    StringEnd = InStr(DirectoryText, ".txt""")
    While (StringEnd <> 0)
  —>   StringLength = 0
  —>   While (InStr(StringEnd - StringLength, Left(DirectoryText, 
  —>   StringEnd),
  —>       """") = 0)
  —>       StringLength = StringLength + 1
  —>   Wend
  —>   StringLength = StringLength - 1
          .
          .
          .
    Wend
End Sub

At this point, we've found a file name in the FTP directory. We know how long it is, so we add it to our listbox List1 this way:

Private Sub Form_Load()
    Dim DirectoryText
    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
    DirectoryText = Inet1.OpenURL("ftp://ftp.microsoft.com")
    DirectoryTextLength = Len(DirectoryText)
    StringEnd = InStr(DirectoryText, ".txt""")
    While (StringEnd <> 0)
        StringLength = 0
        While (InStr(StringEnd - StringLength, Left(DirectoryText, 
        StringEnd),
            """") = 0)
            StringLength = StringLength + 1
        Wend
        StringLength = StringLength - 1
 —>    List1.AddItem Mid(DirectoryText, StringEnd - StringLength + 1,
            StringLength - 1) + ".txt"
               .
               .
               .
    Wend
End Sub

Next, we truncate the directory listing string (we won't need it for anything else, so we remove the parts we've already searched) to remove the already-found file name. Then we loop again to find the next occurrence of ".txt":

Private Sub Form_Load()
    Dim DirectoryText
    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
    DirectoryText = Inet1.OpenURL("ftp://ftp.microsoft.com")
    DirectoryTextLength = Len(DirectoryText)
    StringEnd = InStr(DirectoryText, ".txt""")
    While (StringEnd <> 0)
        StringLength = 0
        While (InStr(StringEnd - StringLength, Left(DirectoryText, 
        StringEnd),
            """") = 0)
            StringLength = StringLength + 1
        Wend
        StringLength = StringLength - 1
        List1.AddItem Mid(DirectoryText, StringEnd - StringLength + 1,
            StringLength - 1) + ".txt"
  —>   DirectoryText = Right(DirectoryText, DirectoryTextLength - 
  —>   StringEnd)
  —>   DirectoryTextLength = DirectoryTextLength - StringEnd
  —>   StringEnd = InStr(DirectoryText, ".txt""")
    Wend
End Sub

At this point, our listbox displays the names of the .txt files:

All that remains is to read the files from the FTP server when the user double-clicks its name in the listbox. We use List1_Click(), creating the full name of the file to fetch by adding "ftp://ftp.microsoft.com/" to the name of the file we are supposed to get in List1.Text:

Private Sub List1_Click()
    RichTextBox1.Text = Inet1.OpenURL("ftp://ftp.microsoft.com/" + List1.Text)
End Sub

That's it—the program is now functional. Run it to see the listing of the .txt files in the FTP server ftp.microsoft.com, as shown in Figure 3.1. Now click a file, such as disclaimer.txt, and it will be downloaded and appear in the rich text box. Our FTP program is a success.

Figure 3.1 Retrieving files from Microsoft via FTP.

That's how to download text. Although we can use the Execute() method, it's usually easier to use OpenURL() if we just want to download a file. We can download binary data, too. Let's look into that now.