VB: FTP

ActiveX    ::    FTP |- 1 -|  2  |

   
Intro

 

It might seem odd to include mention of FTP (an acrostic for File Transfer Protocol) under the heading of - Visual BASIC. But for purposes, here, and in keeping with a report, more or less, of techniques used in the generation of websites such as this, it was with the 'outmoded' VB where was used programmatic control of FTP.

A site like this, with many generated hard-coded pages, can be run from a 'control center'. It can be any application that manages a connection between the computer or node used for the site design, at that moment, and getting any modified/updated page to the server hosting your website. Ideally, one would make changes to the info in a database for a particular page - say this page, for example - then generate the HTML, and then simply press a button - magic - the page is uploaded to the server, into just the right directory. Then everyone browsing your site can view it.

 
Methods

 

There are basically three ways to do this, built in to Windows - that is, apart from purchasing one of very many commercial alternatives (as there are for anything having to do with Windows, Linux, IBM OS, and similar). The first goes back to the release of Win95 - which in its incarnation as Win98SE, is probably still used by not a few people. And that is the application - FTP.EXE. This is a DOS application that opens a session with an FTP server, over the internet we'll say, and then waits in a 'transmit' mode for you to type in various commands to the remote FTP server. In addition, and importantly, instead of waiting and not 'returning the process', the FTP.EXE can also run a script. And that's how it would typically be used.

FTP.EXE, while 'robust', and still being used by folks running Windows XP, is somewhat limited being run even as a script. It's perfectly suitable for simple uploads, when complications are not expected or typically found. I would still have no problem using it to update pages on this site. However, there is an advantage to a more interactive control of the FTP session, reading error messages, changing directories, whatever. Two libraries provide that programmatic control, using Visual BASIC. One is the Internet Transfer Library, a drop-in ActiveX control, which probably predates this next. And the next is the Windows Internet Library. The Internet Transfer Library appears to have certain limitations, and is reported by some to be perhaps not always a reliable upload method. It appears to require much more code and low level control. And I have not personally used it, myself. But the Windows Internet Library is fairly easy to use. Some of the BASIC declarations are likely already included in other modules, they are that common. And then using these few simple declarations and constants to upload via FTP runs you but a few lines of code.

 
FTP.EXE

 

FTP.EXE connects to the server, assuming the server is set up to receive such - and I can't imagine any that would not be as a standard installation. There are certain standard commands sent to the server, as one might see in examining the logs of a freeware or commercial FTP application like WS_FTP or SmartFTP, etc. Commands like - STOR - or LIST. And so on. Some server commands won't even work through FTP.EXE. For those that will, one can use FTP.EXE's commands - literal or quote - to send such commands in the 'server's language. To get a list of FTP commands available on the server, type remotehelp, after you have a connection with the server. FTP.EXE uses its own commands. Just as example, a file can be uploaded or downloaded as one of various types. A binary type seems generally to work. But if one wished, you could specify an ASCII type file. And in the standard FTP commands, that would require the TYPE command. But in FTP.EXE, the command, binary, is used for a TYPE I (Type Image, or binary), and the command ascii, for a TYPE A. And so on.

One may, in a DOS window, begin an interactive FTP.EXE session. Just type - ftp. Windows can probably find where it is. You should get a line beginning with - ftp>. There's no connection. It's just in it's FTP mode. You can end at any time by typing the command - bye, quit, close, or disconnect (the latter two close a connection with the server, the first two do that and also exit the FTP.EXE session). These commands are case-sensitive, by the way. Instead, type the word - help. And that dumps the relatively few commands available to FTP.EXE. Here would be a quick, but unrealistic, FTP.EXE session:

 
 9:14 C:\WINDOWS >ftp
ftp> help
Commands may be abbreviated. Commands are:
 
!             delete        literal       prompt        send
?             debug         ls            put           status
append        dir           mdelete       pwd           trace ascii         disconnect    mdir          quit          type
bell          get           mget          quote         user
binary        glob          mkdir         recv          verbose
bye           hash          mls           remotehelp
cd            help          mput          rename
close         lcd           open          rmdir
Session open - now in FTP mode. But there's no connection with the server.
 
Help or the question mark shows the commands available in FTP.EXE
ftp> ? put
put            Send one file
help and ? are the same, and present a terse description of each FTP.EXE command
ftp> ? !
!               Escape to the shell
ftp> !
 9:15 C:\WINDOWS >
 9:15 C:\WINDOWS >exit
ftp>
exclamation mark used to break out of FTP session, even while the session keeps on running. Type - exit - to return to the FTP session
ftp> debug
Debugging On .
Echoes the USER and PASS, seen below
ftp> open ftp.yourserver.com
Connected to ftp.yourserver.com.
220 Microsoft FTP Service
User (ftp.yourserver.com:(none))> username
---> USER username
331 Password required for username
Password:
---> PASS whatever
230 User username logged on
Log on to remote server using - open. As you type your password, nothing is recorded in the window. Debug, however, shows what you typed in. And now we are logged onto the server, just as if using WS_FTP or any FTP application.
ftp> quote syst
---> syst
215 Windows_NT
Using quote to run a server command which identifies the type of server
ftp> quit
 9:15 C:\WINDOWS >_
Bye

   
Two Parts

 

There are two parts to the operation. First, one has to collect the data for the file and directories. Then one can decide which method to use to upload it to the server. Try this for an example of collecting the basic data, in Visual BASIC of course:

 
Private Sub sRunFTPUpload(boolImg As Boolean)
    Dim strFTPserver As String, strFTPpath As String, strLocalPath As String, strFilename As String
    Dim strUser As String, strPW As String, FileNum, strWrite As String
    Dim strWhere As String, strRelLocal As String, strT As String
    Dim hTaskID As Long, hProcess As Long, lngImgID As Long, boolRtn As Boolean
 
    If IsNull(Me!anID) Then Exit Sub
 
    strWhere = "anid=" & Me.Parent.anID
 
    lngImgID = Me!anID
    strT = fLookUp("txRemoteRootPath,txRemoteHome,txLocalRootPath,txUser,txPW", "tblProjects", strWhere)
    strUser = fDfield(strT, 4)
    strPW = fDfield(strT, 5)
    strFTPserver = fDfield(strT, 1)
    strLocalPath = IIf(boolImg, fGetFullPath(lngImgID), fGetFullHTMLPath(lngImgID))
    strRelLocal = fGetRelURL(fDfield(strT, 3), strLocalPath)
    If boolImg Then fStripRightDir strLocalPath
    sChopLeft strRelLocal, 1
    sChopRgt strLocalPath, 1
    strFTPpath = fDfield(strT, 2) & strRelLocal
    strFilename = IIf(boolImg, Me.tboFilename, Me!tboHTML & ".htm")

 
Suffice to say, this is an actual routine used to collect info and upload it to this very site. The boolImg (some would prefer bImg, rather than, bool), is just a flag to indicate whether a page containing the image, or the image itself, is being uploaded.

 
 

Getting the user-name, password, and ftp address is self-explanatory. The filename is also easy. But the source and target paths have to be found. Importantly, as well, the source path cannot end with a slash, "/". That's stripped out, here, with a custom 'chop' command, the sChopRgt. The chop left command removes a leading dot inserted by the routine which finds not the absolute directory/host and path, but the relative path to the file. The local file can be an absolute path. That's fine. But the remote path and directory are relative to the current directory selected on the remote server. The cd command changes the remote directory, once the connection is established. In this case, the server uses a home directory - named, "/webroot" (stored in the field, txRemoteHome, in this example; found as fDfield #2). So after logging in, one has to get to the "/webroot" directory, and then go from there. In fact, in the example, below, the local directory is concatenated to this home directory and then changed on the server in one shot.

 
FTP.EXE scripting

 

What makes FTP.EXE useful is that it can run a script, rather than locking you up in an interactive session - as shown above. One of the parameters is "-s:", to specify a script file.

 
C:\WINDOWS >ftp -s:script2.txt

 

And just save that as a .BAT, batch file. Script2.txt, or just whatever you want to call it, is the script file. So you have two files, this one-line batch file and the text script file, both in some directory. Use the Windows Shell to execute the batch file. In fact, one can wait on the .BAT file to finish. One can wait for the script to conclude, before moving on to the next statement/command in Visual BASIC. Normally, the Shell command is called and forgotten. It runs 'asynchronously'. But up until Office 2002, I believe, the Shell command call from Visual BASIC returned a process handle to the DOS window opened to run FTP.EXE in this example. And one could use that handle to identify the app/window, and whether or not it closed. So one could get it to close on completion of the script simply by creating a third file, what used to be called a .PIF file, where one sets the .BAT file to "Close on Exit". So you have three files, then, the batch file which points to a script file with a set and known name, the script file itself which is generated from VB, and this 'properties'/PIF file associated with the batch file where you checked the box for the batch file to close on exit when finished.

 
    strWrite = "open " & strFTPserver & vbCrLf & _
                 strUser & vbCrLf & _
                 strPW & vbCrLf & _
                 "cd " & strFTPpath & vbCrLf & _
                 "lcd " & strLocalPath & vbCrLf & _
                 IIf(boolImg, "binary", "ascii") & vbCrLf & _
                 "send " & strFilename & " " & strFilename & vbCrLf & _
                 "quit"
 
     FileNum = FreeFile
     Open "C:\yoursite\home\somedirectory\ftps.txt" For Output As #FileNum
     Print #FileNum, strWrite
     Close #FileNum
 
     hTaskID = Shell("C:\yoursite\home\somedirectory\ftp.bat", 6)

 

So here you are generating the script file. The local directory, holding the file to be uploaded to the server, is selected with the lcd (change local direc) command. The remote directory is specified, with cd, which is where the file already is or is supposed to go. And providing the filename itself, is the last thing, using the send command. So again FTP.BAT was modified by Properties, Program, to "Close on Exit". That created the third 'properties' file. Now we are here calling the script file, FTPS.TXT. And FTP.BAT has to reflect that. All three files are in the same directory, and coincidentally are only 1K in length. So the Shell command simply executes the .BAT file which contains one single line:

 
ftp -s:C:\yoursite\home\somedirectory\ftps.txt

 

That's it. A tab/box will appear in the Windows tab bar, typically placed at the bottom of the screen. When the FTP.EXE concludes, the tab will disappear. File successfully uploaded. It goes very quickly. The only other thing is then to watch the window to see when it closes. At least in Office 2000 and before, Shell returned a process handle. That can be read as follows:

 
    Public Const SHELL_SYNCHRONIZE = &H100000
    Public Const SHELL_INFINITE = -1&
 
    Public Declare Function WaitForSingleObject Lib "kernel32" _
        (ByVal hHandle As Long, _
        ByVal dwMilliseconds As Long) As Long
 
    Public Declare Function OpenProcess Lib "kernel32" _
        (ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Long, _
        ByVal dwProcessId As Long) As Long
 
    Public Declare Function CloseHandle Lib "kernel32" _
        (ByVal hObject As Long) As Long
 


 
    hTaskID = Shell("C:\yoursite\home\somedirectory\ftps.txt", 6)
 
    hProcess = OpenProcess(SHELL_SYNCHRONIZE, 0, hTaskID)
    If hProcess <> 0 Then
        WaitForSingleObject hProcess, SHELL_INFINITE
        CloseHandle hProcess
    End If
 
    If hTaskID Then Me.lblDone2.Visible = True
    Me.TimerInterval = 800
 

 
 

WaitforSingleObject is pretty common, and might already be declared in your various API declarations, in Visual BASIC. The last just makes a little label with the word - DONE - briefly appear. A low number of 800 is set into the timer, and then the Timer function is called, after this interval, which makes the label once again invisible, and resets the timer. You know the FTP.EXE window has closed. And that's it.

That's not so bad, as things go. And it works fine, I'm sure, right up through XP (though it's said some had trouble connecting with various FTP apps after XP SP2 - I don't know). There's nothing wrong with writing a batch script for FTP.EXE and running it. But there's another way which can be manipulated in Visual BASIC, and which provides more options and more programmatic control and branching based on conditions.

Continue