The Visual Basic online help for the Internet Transfer control demonstrates the pieces you would use to create an FTP browser, but it doesn't assemble those pieces into a working application. This is a problem because the Internet Transfer control is asynchronoushow the events and error handling interact is the most difficult aspect of using the control.
Figure 7-6 below shows a simple FTP browser I've created using two text boxes and an Internet Transfer control. You enter the URL of an FTP server in the Address text box, and then select a file or a directory from the contents text box. If the selection is a directory, the application displays that directory. If the selection is a file, the browser saves the file in the Windows Temp directory.
When the user presses Enter, the Address text box executes requests by setting the Internet Transfer control's URL property and calling the Execute method. The OpenURL method performs the same action when requesting a specific file. However, when you use the OpenURL method to return the contents of a directory, HTML source code indicating the directory contents typically is returned. Therefore, in this example, I have steered clear of the OpenURL method. The code following Figure 7-6 shows the KeyPress event procedure for the txtAddress text box.
Figure 7-6. A simple FTP browser created using the Internet Transfer control.
Private Sub txtAddress_KeyPress(KeyAscii As Integer)
If KeyAscii = Asc(vbCr) Then
`Eat keystroke
KeyAscii = 0
`Select text
txtAddress.SelStart = 0
txtAddress.SelLength = Len(txtAddress)
On Error GoTo errOpenURL
`Set FTP address to view
inetBrowse.URL = txtAddress
`Get directory
inetBrowse.Execute , "Dir "
txtAddress = inetBrowse.URL
End If
Exit Sub
errOpenURL:
Select Case Err.Number
Case icBadUrl
MsgBox "Bad address. Please reenter."
Case icConnectFailed, icConnectionAborted, _
icCannotConnect
MsgBox "Unable to connect to network."
Case icInetTimeout
MsgBox "Connection timed out."
Case icExecuting
`Cancel previous request
inetBrowse.Cancel
`Check whether cancel worked
If inetBrowse.StillExecuting Then
Caption = "Couldn't cancel request."
`Resubmit current request
Else
Resume
End If
Case Else
Debug.Print Err.Number, Err.Description
End Select
End Sub
It's important to trap any errors that occur when you submit a request to the Internet Transfer control. The icExecuting error is particularly important. The Internet Transfer control processes all requests asynchronously; however, it can process only one request at a time. If you cancel a pending request, be sure to check the StillExecuting property before resuming, as shown in the previous code. Some requests can't be canceled and using only a Resume statement will result in an infinite loop!
The following code shows the DblClick event procedure for the txtContents text box, in which directory listings are displayed. This code builds the URL string and executes a Dir command if the selection is a subdirectory, or a Get command if the selection is a file.
Private Sub txtContents_DblClick()
`Browse selected directory
If txtContents.SelLength Then
`If selection is a directoryDear John, How Do I...
If Right(txtContents.SelText, 1) = "/" Then
`Add selected item to address
txtAddress = txtAddress & "/" & _
Left(txtContents.SelText, _
txtContents.SelLength - 1)
`Trap errors (important!)
On Error GoTo errBrowse
`Show directory
mstrDir = Right(txtAddress, Len(txtAddress) _
- Len(inetBrowse.URL))
inetBrowse.Execute , "Dir " & mstrDir & "/*"
`Otherwise, it's a file, so retrieve it
Else
Dim strFilename
`Build pathname of file
mstrDir = Right(txtAddress, Len(txtAddress) _
- Len(inetBrowse.URL)) & "/" & _
txtContents.SelText
mstrDir = Right(mstrDir, Len(mstrDir) - 1)
strFilename = mstrDir
Do
strFilename = Right(strFilename, _
Len(strFilename) - InStr(strFilename, "/"))
Loop Until InStr(strFilename, "/") = 0 `Retrieve file
inetBrowse.Execute , "Get " & mstrDir & _
" " & mstrTempDir & strFilename
End If
End If
Exit Sub
errBrowse:
If Err = icExecuting Then
`Cancel previous request
inetBrowse.Cancel
`Check whether cancel worked
If inetBrowse.StillExecuting Then
Caption = "Couldn't cancel request."
`Resubmit current request
Else
Resume
End If
Else
`Display error
Debug.Print Err & " " & Err.Description
End If
End Sub
The Execute and OpenURL methods trigger the StateChanged event. It's important to remember that both methods do this, because OpenURL appears to be a synchronous method; however, StateChanged events still occur and can cause problems with reentrancy.
The following code updates the form's caption to keep you abreast of the request's progress and then uses the GetChunk method to retrieve a directory listing if the command executed was Dir.
Private Sub inetBrowse_StateChanged(ByVal State As Integer)
Select Case State
Case icError
Debug.Print inetBrowse.ResponseCode & " " & _
inetBrowse.ResponseInfo
Case icResolvingHost, icRequesting, icRequestSent
Caption = "SearchingDear John, How Do I... "
Case icHostResolved
Caption = "Found."
Case icReceivingResponse, icResponseReceived
Caption = "Receiving data."
Case icResponseCompleted
Dim strBuffer As String
`Get data
strBuffer = inetBrowse.GetChunk(1024)
`If data is a directory, display it
If strBuffer <> "" Then
Caption = "Completed."
txtContents = strBuffer
Else
Caption = "File saved in " & _
mstrTempDir & "."
End If
Case icConnecting, icConnected
Caption = "Connecting."
Case icDisconnecting
Case icDisconnected
Case Else
Debug.Print State
End Select
End Sub
NOTE
The current documentation suggests that GetChunk will work with the Execute method's GET command, but that does not seem to be the case. The GET command's syntax specifies a source file and a destination file; therefore, GetChunk is not needed when you are copying a file from a server.
The complete code for the FTP browser, including the GetTempPath API function declaration and the Form_Load event procedure, can be found on the companion CD-ROM.