A lot of folks have need of transferring files to and from an ftp server.
Well, you can end your search. I have (with a lot of help from news2news.com)
made some routines to utilize the ftp protocol using API calls. There is
always the MS Inet control, and there is the Winsock control, but if you all
you want is a command line transfer, you can use that API calls.
The first is FTPGet.PRG, followed by FTPPut.PRG, then FtpDelete.PRG.
Since none of the routines are really interactive or an end user interface,
there is not much error checking. It is up to you to put that in to suit your
needs.
I have also made an interactive FTP client form which also utilizes the API
calls above. It was a good lesson in FTP usage. It will browse both local
drives and remote servers, as well as transfer files back and forth. It isn't
totally refined, but it is a good starting point.
Go to my web site: http://www.davesummers.net/foxprolinks.htm
and download it. Have fun!
A couple things to point out here, notice that several of the the API calls are
common in these routines. The exceptions are of course, FtpGetFile, FtpPutFile
and FtpDeleteFile.
So they can all be declared early in your main program and not have to be
're'declared. Also note that the most common error is "Unable to find entry point"
or "Can't find entry point..." or something along those lines. That is caused by
not using the proper case for both the declare and execution on the API calls.
I.e., FtpPutFile must be written as "FtpPutFile", not "FTPPUTFILE" or "ftpputfile"
and so on. I point this out because if you're not careful, beautify can really
trash things.
Note that FtpGetFile, FtpPutFile and FtpDeleteFile have been made
BOLD in this
faq. There is an issue here that when the code is posted, anything starting with
'ftp' that is not surrounded by quotes, will get converted to lowercase. That
causes an API error as stated in the previous paragraph.
**********************************************************************************
*... FTPGet.PRG ...*
Code:
PARAMETERS lcHost, lcUser, lcPwd, lcRemoteFile, lcNewFile, lnXFerType
*.................................................................................
*: Usage: DO ftpget WITH ;
*: 'ftp.host', 'name', 'password', 'source.file', 'target.file'[, 1 | 2]
*:
*: Where: lcHost = Host computer IP address or name
*: lcUser = user name - anonymous may be used
*: lcPwd = password
*: lcRemoteFile = source file name
*: lcNewFile = target file name
*: lnXFerType = 1 (default) for ascii, 2 for binary
*.................................................................................
*...set up API calls
DECLARE INTEGER InternetOpen IN wininet;
STRING sAgent, INTEGER lAccessType, STRING sProxyName,;
STRING sProxyBypass, STRING lFlags
DECLARE INTEGER InternetCloseHandle IN wininet INTEGER hInet
DECLARE INTEGER InternetConnect IN wininet.DLL;
INTEGER hInternetSession,;
STRING lcHost,;
INTEGER nServerPort,;
STRING lcUser,;
STRING lcPassword,;
INTEGER lService,;
INTEGER lFlags,;
INTEGER lContext
DECLARE INTEGER
FtpGetFile
Code:
IN wininet;
INTEGER hFtpSession, ;
STRING lcRemoteFile,;
STRING lcNewFile, ;
INTEGER fFailIfExists,;
INTEGER dwFlagsAndAttributes,;
INTEGER dwFlags, ;
INTEGER dwContext
lcHost = ALLTRIM(lcHost)
lcUser = ALLTRIM(lcUser)
lcPwd = ALLTRIM(lcPwd)
lcRemoteFile = ALLTRIM(lcRemoteFile)
lcNewFile = ALLTRIM(lcNewFile)
sAgent = "vfp"
sProxyName = CHR(0) &&... no proxy
sProxyBypass = CHR(0) &&... nothing to bypass
lFlags = 0 &&... no flags used
*... initialize access to Inet functions
hOpen = InternetOpen (sAgent, 1,;
sProxyName, sProxyBypass, lFlags)
IF hOpen = 0
WAIT WINDOW "Unable to get access to WinInet.Dll" TIMEOUT 2
RETURN
ENDIF
*... The first '0' says use the default port, usually 21.
hFtpSession = InternetConnect (hOpen, lcHost,;
0, lcUser, lcPwd, 1, 0, 0) &&... 1 = ftp protocol
IF hFtpSession = 0
*... close access to Inet functions and exit
= InternetCloseHandle (hOpen)
WAIT WINDOW "Unable to connect to " + lcHost + '.' TIMEOUT 2
RETURN
ELSE
WAIT WINDOW "Connected to " + lcHost + " as: [" + lcUser + "]" TIMEOUT 1
ENDIF
*... 0 to automatically overwrite file
*... 1 to fail if file already exists
fFailIfExists = 0
dwContext = 0 &&... used for callback
WAIT WINDOW 'Transferring ' + lcRemoteFile + ' to ' + lcNewFile + '...' NOWAIT
lnResult =
FtpGetFile
Code:
(hFtpSession, lcRemoteFile, lcNewFile,;
fFailIfExists, 128, lnXFerType,;
dwContext)
*... 128 = #define FILE_ATTRIBUTE_NORMAL 0x00000080
*... See CreateFile for other attributes
* close handles
= InternetCloseHandle (hFtpSession)
= InternetCloseHandle (hOpen)
IF lnResult = 1
*... successful download, do what you want here
WAIT WINDOW 'Completed.' TIMEOUT 1
MODI FILE (lcNewFile)
ELSE
WAIT WINDOW "Unable to download selected file" TIMEOUT 2
ENDIF
RETURN
*** End of FTPGet.PRG *************************************************************
**********************************************************************************
*... FTPPut.PRG ...*
Code:
PARAMETERS lcHost, lcUser, lcPassword, lcSource, lcTarget, lnXFerType
*.................................................................................
*: Usage: DO ftpput WITH ;
*: 'ftp.host', 'name', 'password', 'source.file', 'target.file'[, 1 | 2]
*:
*: Where: lcHost = Host computer IP address or name
*: lcUser = user name - anonymous may be used
*: lcPassword = password
*: lcSource = source file name (remote)
*: lcTarget = target file name (local)
*: lnXFerType = 1 (default) for ascii, 2 for binary
*.................................................................................
DECLARE INTEGER InternetOpen IN wininet.DLL;
STRING sAgent,;
INTEGER lAccessType,;
STRING sProxyName,;
STRING sProxyBypass,;
STRING lFlags
DECLARE INTEGER InternetCloseHandle IN wininet.DLL INTEGER hInet
DECLARE INTEGER InternetConnect IN wininet.DLL;
INTEGER hInternetSession,;
STRING lcHost,;
INTEGER nServerPort,;
STRING lcUser,;
STRING lcPassword,;
INTEGER lService,;
INTEGER lFlags,;
INTEGER lContext
DECLARE INTEGER
FtpPutFile
Code:
IN wininet.DLL;
INTEGER hConnect,;
STRING lpszLocalFile,;
STRING lpszNewRemoteFile,;
INTEGER dwFlags,;
INTEGER dwContext
PUBLIC hOpen, hFtpSession
lcHost = ALLTRIM(lcHost)
lcUser = ALLTRIM(lcUser)
lcPassword = ALLTRIM(lcPassword)
lcSource = ALLTRIM(lcSource)
lcTarget = ALLTRIM(lcTarget)
IF connect2ftp (lcHost, lcUser, lcPassword)
WAIT WINDOW 'Transferring....' NOWAIT
IF
FtpPutFile
Code:
(hFtpSession, lcSource,;
lcTarget, lnXFerType, 0) = 1
WAIT WINDOW lcSource + ' transferred.' TIMEOUT 2
ENDIF
= InternetCloseHandle (hFtpSession)
= InternetCloseHandle (hOpen)
ENDIF
*..................... connect2ftp .........................................
*... Makes sure there is actually a valid connection to the host
FUNCTION connect2ftp (lcHost, lcUser, lcPassword)
* open access to Inet functions
hOpen = InternetOpen ("vfp", 1, 0, 0, 0)
IF hOpen = 0
? "Unable to get access to WinInet.Dll"
RETURN .F.
ENDIF
*... The first '0' says use the default port, usually 21.
hFtpSession = InternetConnect (hOpen, lcHost,;
0, lcUser, lcPassword, 1, 0, 0) &&... 1 = ftp protocol
IF hFtpSession = 0
* close access to Inet functions and exit
= InternetCloseHandle (hOpen)
? "FTP " + lcHost + " is not available"
RETURN .F.
ELSE
? "Connected to " + lcHost
ENDIF
RETURN .T.
RETURN
*** End of FTPPut.PRG *************************************************************
Now if you want to delete the remote file after downloading it,
you can use FtpDelete.PRG:
**********************************************************************************
*... FtpDelete.PRG ...*
Code:
PARAMETERS lcHost, lcUser, lcPwd, lcRemoteFile
*.................................................................................
*: Usage: DO ftpdelete WITH ;
*: 'ftpserver.host', 'name', 'password', 'delete.file'
*:
*: Where: lcHost = Host computer IP address or name
*: lcUser = user name - anonymous may be used
*: lcPwd = password
*: lcRemoteFile = file to delete
*.................................................................................
*...set up API calls
PUBLIC hOpen, hFtpSession
DECLARE INTEGER InternetOpen IN wininet.DLL;
STRING sAgent,;
INTEGER lAccessType,;
STRING sProxyName,;
STRING sProxyBypass,;
STRING lFlags
DECLARE INTEGER InternetCloseHandle IN wininet.DLL INTEGER hInet
DECLARE INTEGER InternetConnect IN wininet.DLL;
INTEGER hInternetSession,;
STRING sServerName,;
INTEGER nServerPort,;
STRING sUsername,;
STRING sPassword,;
INTEGER lService,;
INTEGER lFlags,;
INTEGER lContext
DECLARE INTEGER
FtpDeleteFile
Code:
IN wininet.DLL;
INTEGER hConnect,;
STRING lpszFileName
*... open access to Inet functions
hOpen = InternetOpen ("vfp", 1, 0, 0, 0)
IF hOpen = 0
? "Unable to get access to WinInet.Dll"
RETURN .F.
ENDIF
*... connect to FTP host
hFtpSession = InternetConnect (hOpen, lcHost, 0,;
lcUser, lcPwd, 1, 0, 0)
IF hFtpSession = 0
* close access to Inet functions and exit
= InternetCloseHandle (hOpen)
WAIT WINDOW "FTP " + strHost + " is not available" TIMEOUT 2
ELSE
WAIT WINDOW "Connected to " + lcHost + " as: [" + lcUser + "]" NOWAIT
IF
FtpDeleteFile
Code:
(hFtpSession, lcRemoteFile) = 1
WAIT WINDOW lcRemoteFile + ' deleted.' TIMEOUT 1
ELSE
WAIT WINDOW 'Error deleting ' + lcRemoteFile + "." TIMEOUT 1
ENDIF
ENDIF
= InternetCloseHandle (hFtpSession)
= InternetCloseHandle (hOpen)
*** End of FTPDelete.PRG *************************************************************