by Richard Russell, March 2010, amended June 2012
This article describes how to upload one or more files to an FTP server. The first step is to define some constants:
FTP_TRANSFER_TYPE_ASCII = 1 FTP_TRANSFER_TYPE_BINARY = 2 _INTERNET_DEFAULT_FTP_PORT = 21 : REM default port for FTP servers _INTERNET_SERVICE_FTP = 1 _INTERNET_FLAG_PASSIVE = &8000000 OPEN_TYPE_PRECONFIG = 0 : REM use registry configuration OPEN_TYPE_DIRECT = 1 : REM direct to net OPEN_TYPE_PROXY = 3 : REM via named proxy OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY = 4 : REM prevent using Java
Next, get the necessary function entry points:
SYS "LoadLibrary", "WININET.DLL" TO wininet% SYS "GetProcAddress", wininet%, "InternetOpenA" TO `InternetOpen` SYS "GetProcAddress", wininet%, "InternetConnectA" TO `InternetConnect` SYS "GetProcAddress", wininet%, "FtpSetCurrentDirectoryA" TO `FtpSetCurrentDirectory` SYS "GetProcAddress", wininet%, "FtpPutFileA" TO `FtpPutFile` SYS "GetProcAddress", wininet%, "InternetCloseHandle" TO `InternetCloseHandle`
We are now ready to open an internet connection:
REM Open an internet connection: SYS `InternetOpen`, "BBC BASIC for Windows", OPEN_TYPE_PRECONFIG, 0, 0, 0 TO hOpen% IF hOpen% = 0 ERROR 100, "Cannot open internet connection"
This code will normally be suitable, but in certain special circumstances an alternative OPEN_TYPE constant may need to be used (see the definitions above); details may be found in the Microsoft documentation.
Once a successful internet connection has been made, a connection must be made to the remote FTP server:
REM Connect to the FTP server: SYS `InternetConnect`, hOpen%, "ServerName", _INTERNET_DEFAULT_FTP_PORT, \ \ "Username", "Password", \ \ _INTERNET_SERVICE_FTP, 0, 0 \ \ TO hConnection% IF hConnection% = 0 ERROR 101, "Cannot open FTP connection"
Here ServerName, Username and Password have been shown as constant strings, but of course they could alternatively be string variables (e.g. ServerName$, Username$ and Password$). The Server Name should be either a valid host name (e.g. ftp.bbc.co.uk) or an IP address (e.g. 18.104.22.168).
If the FTP server you are using requires a passive connection, specify the INTERNET_FLAG_PASSIVE flag in the InternetConnect function:
REM Connect to the FTP server: SYS `InternetConnect`, hOpen%, "ServerName", _INTERNET_DEFAULT_FTP_PORT, \ \ "Username", "Password", \ \ _INTERNET_SERVICE_FTP, _INTERNET_FLAG_PASSIVE, 0 \ \ TO hConnection% IF hConnection% = 0 ERROR 101, "Cannot open FTP connection"
Optionally you can now navigate to a sub-directory in which you want to store the file(s):
REM Set the current directory: SYS `FtpSetCurrentDirectory`, hConnection%, "testing" TO res% IF res% = 0 ERROR 102, "Cannot set current directory"
Once again the sub-directory name has been shown as a constant string, but it could be a variable.
Now we can transfer the file itself:
REM Upload the file: SYS `FtpPutFile`, hConnection%, "C:\test.htm", "test.htm", \ \ FTP_TRANSFER_TYPE_ASCII, 0 TO res% IF res% = 0 ERROR 103, "Cannot upload file"
The location of the source file, and the name it should be given on the destination FTP server, are shown here as constant strings, but they could be variables.
As shown the file will be transferred in text format, which means the line terminations will automatically be converted as required (e.g. from CRLF to LF). If you want to transfer the file in binary format, for example it is an executable program or ZIP archive, then substitute FTP_TRANSFER_TYPE_BINARY.
You can transfer as many files as you like, by repeating the above code snippet. Once all the files have been successfully transferred, close the connection as follows:
REM Close the FTP connection: SYS `InternetCloseHandle`, hConnection% REM Close the internet connection: SYS `InternetCloseHandle`, hOpen%
Ideally you should trap errors using ON ERROR and in the event of an error occurring close the connection, for example by copying the above code into a 'cleanup' routine called from your error handler.