Well, the final part of the Inet series has finally arrived! This week, I will take you through looking at using the Inet control to perform FTP operations. We will look at connecting to an FTP server, getting directory and file listings, removing files on the server, uploading and downloading files and other FTP tasks. At the end of this article you will also see a downloadable project that contains all the code from this article, as well as a class module that includes all the API declares for the Inet FTP commands (ie you don't need to control)
Using the Internet Transfer Control: Part 3
Lets start off with the basics first: connecting.
The first thing we need to do is to set the Protocol property of the Inet control to icFTP. We also need to specify a server address (in the form of a URL) and a username and password to login. If the FTP site doesn't require a username and password, then you can just leave them blank. All of these properties can be set using the Property Page in the IDE, or you can set them at run time:
With Inet1 .Cancel .Protocol = icFTP .URL = "localhost" .Username = "" .Password = "" End With
You may have noticed that there is no specific Connect command in the Inet control, so what we have to do is use the Execute command, which allows us to execute a special FTP command.
(If you have ever used DOS before then you will be familiar with some of the commands used)
Just think back to the last time that you used an FTP program. What is the first thing it does after connecting? Show a list of all the directories and files in the default directory. This can be done using a DIR command and some clever stuff in the Inet's StateChanged event.
Here are some of the commands that you will be using when you FTP into a server:
CD - Change directory
CDUP - Change to the parent directory. The same as "CD .."
DELETE - Deltes a file
DIR - Retrieves the current directory listing
GET - Retrieves a file
MKDIR - Makes a new directory
PUT - Uploads a file
PWD - Sends a password
QUIT - Ends an FTP session
RECV - The same as GET
RENAME - Renames a file
RMDIR - Deletes a directory
SEND - Same as PUT
SIZE - Retrieves the size of a file
This is all very well and true, but how do I actually connect and get the contents of the root directory? Lets find out.
Well, in the Inet's StateChanged event, we need to monitor when data comes in and then do some trickery to get what the server is sending. Firstly, it is a good idea to store the current command (e.g. GET) as a module level variable. This way all the procedures can access it and we know what we are currently doing.
For example, if we wanted a list of directories, then we would set our variable to DIR, and then use the Execute method. This way when we are in the StateChanged event, a completely different procedure, we still know what the last command was.
The StateChanged event procedure provides us with one parameter, State. We can use a Select Case statement to determine what is currently going on. Now, the server only sends back data after the state of icResponseCompleted, so we need to stick in another Select Case statement to find out what command we are executing.
Lets quickly recap on the code. Here is what we have so far in the StateChanged event:
Private Sub Inet1_StateChanged(ByVal State As Integer) Select Case State Case icResponseCompleted Select Case strCmd Case "DIR" End Select End Select End Sub
OK. As the StateChanged event only passes the State parameter, we need to manually get the data that is being sent by the server. We do this using the GetChunk method. Because of the way things are, we can only get 512 characters at a time, so we need to set-up a loop that will make sure that we get all the data. It looks something like this:
Do strNewData = Inet1.GetChunk(512,icString) DoEvents If Len(strData) = 0 Then Exit Do strData = strData & strNewData Loop
Notice the use of DoEvents. This is very important because we must give the server time to sort itself out otherwise we will run into a whole load of problems.
If you are currently testing out this code, you will notice that the contents of strData are not exactly 'user friendly' at the moment. We still need to go through and format the data, for whatever control we are going to load it into. Each file and directory is in the string and at the end of each one, a vbCrlf character can be found. This makes it easy to parse out all the different items using some of VBs great string functions:
Do While Len(strData) intPos = Instr(strData,vbCrlf) If intPos Then strItem = Left$(strData, intPos - 1) strData = Mid$(strData, intPos + 2) Else strItem = strData strData = "" End If Loop
But how do we know the difference between a file and a directory? Well, fortunately all directories come with a trailing /, so we can look for that when we want to do something with the item:
strItem = lstDir.List(lstDir.ListIndex) If strItem = ".." Or Right$(strItem,1) = "/" Then DoEvents If strItem = ".." Then strCmd = "CDUP" Inet1.Execute ,strCmd Else strCmd = "CD " & Left$(strItem, Len(strItem) -1) Inet1.Execute ,strCmd End If End If
OK. So now we have a list of directories. The next thing we are going to learn, is how to upload files.
This starts to get a bit simpler, because it is mainly a case of using the Execute command.
The syntax of the PUT command is as follows:
PUT localfile, remotefile
Here is a sample:
Inet1.Execute ,"PUT c:\myfile.txt /myfile.txt"
(Remember to include that preceeding '/')
To download a file, use the GET command:
GET remotefile, localfile Inet1.Execute ,"GET myfile.txt c:\myfile.txt"
To delete a file, you need to use the DELETE command:
DELETE remotefile Inet1.Execute ,"DELETE myfile.txt"
And finally, renaming a file can be done using, yes, you guessed it the RENAME command:
RENAME oldname,newname Inet1.Execute ,"RENAME myfile.txt mynewfile.txt"
OK. Now that we have finsihed with files, lets move onto directories.
When handling directories, we need to add and delete them. For DOS gurus, this should be like the good old days! Simply use the MKDIR and RMDIR to make and remove directories. You should be aware of the syntax for both of these commands:
Pretty simple, but you must remember to place the / in at the correct places, otherwise you will have problems.
So, that's almost it. But one more thing, what if we want to create a COM object (say a class module) that encapsulates all of this logic to make an easy to use object for FTP? Will we have to add a form just for the control? Well, thanks to Chris Eastwood, we don't! He has gone through the MS documentation and extracted the Inet API calls, so all the functionality of the Inet control can be accessed through the Wininet DLL! And, even better, he has wrapped it up in a useful class module with some simple functions to operate an FTP program.
OK. Demo time. I was going to create demo project for this article, but then found someone already had. Matt Hart (www.matthart.com), a VB expert has written a good example of using the Inet control for FTP comms, and as long as you can stand his variable naming methods, then it should be very useful to you as a started project.
As you progress, you may want to use a treeview or a listview to display the contents of both the server and your users local hard disk. I suggest you check out all the tips we have on these controls, along with over 300 others: VB Square Tips!
Oops! Almost forgot about the demo projects!