FTP with VFP

I tried looking for a VFP 7 specific forum, since to this problem it is irrelevant (i think) which version of VFP i'm usding i posted here. If there is a more apropriate place please be so kind as directing me to it. Sad


Hi, i'm trying to use FTP integrated in VFP 7 and Win XP SP2 to upload/download/delete files in an FTP server but with limited success.

The code i am using i took from some other VFP support site but it was so long ago that i can't remember where (i only started trying to implement it now) so i can't contact them to help me. Maybe some of you have experience working with this stuff and can give me a helping hand, either by correcting the problem with this code or directing me to some other code that does the same thing.

The code has 3 procedures, UPLOAD_FTP (to upload files to the server), DOWNLOAD_FTP (to download files from the server) and DELETE_FTP (to delete files on the server).

Both UPLOAD and DELETE work perfectly, only DOWNLOAD has problems.
I can upload a file to the server with no problem, i check the file size and all is OK. If i download that file using an FTP program the file is downloaded with no problem. If i use this code to download that same file the file size increases!
From that i can conclude that the problem is not in the upload part of the code.

As an example, if i upload "samples.vct" (133.696 bytes on disc) i have no problem, on the server the file keeps those same 133.696 bytes. If i download the file with some FTP program the file is downloaded correctly with the same 133.696 bytes. If i use this code to download that file the file size becames 136.508 bytes on disk!

This is true for any file, but the number of bytes added is *roughly* aritmetic, twice the size twice the number of extra bytes. I think they might be some sort of checkdigit bytes or something, and that probably this can be solved configuring some of the parameters in the code but i realy have no experience with this comunications stuff.

Can anyone help, has anyone any experience with this sort of stuff
The code is posted next. (try it please)
It is part of a larger code but i pasted only the relevant parts, declare the inicial parameters and then to use it there is a section in the middle with:

* DO UPLOAD_FTP
* DO DOWNLOAD_FTP
* DO DELETE_FTP

Just remove the asterisc from whatever you want to test.

Thanks in advance for your help, and for the patience in reading this long message.

*************************************************************************************


* server adress
ftp_ip="111.22.333.44"
* username
ftp_user="username"
* password
ftp_pass="password"
* local directory
vcLocalDir="C:\TEST\"
* FTP server directory
vcServerDir="/docs/http/transfer/test/"
* file name
vcFilename="samples.vct"

 

#DEFINE GENERIC_READ     2147483648
#DEFINE GENERIC_WRITE     1073741824
#DEFINE INTERNET_INVALID_PORT_NUMBER 0
#DEFINE INTERNET_OPEN_TYPE_DIRECT  1
#DEFINE INTERNET_OPEN_TYPE_PROXY  3
#DEFINE INTERNET_DEFAULT_FTP_PORT  21
#DEFINE INTERNET_FLAG_ASYNC    268435456
#DEFINE INTERNET_FLAG_FROM_CACHE  16777216
#DEFINE INTERNET_FLAG_OFFLINE   16777216
#DEFINE INTERNET_FLAG_CACHE_IF_NET_FAIL 65536
#DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0
#DEFINE FTP_TRANSFER_TYPE_ASCII   1
#DEFINE FTP_TRANSFER_TYPE_BINARY  2
#DEFINE INTERNET_SERVICE_FTP   1
#DEFINE INTERNET_SERVICE_GOPHER   2
#DEFINE INTERNET_SERVICE_HTTP   3
#DEFINE FILE_ATTRIBUTE_NORMAL   128
*
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 FtpGetFile IN WININET.DLL;
 INTEGER hFtpSession,;
 STRING  lpszRemoteFile,;
 STRING  lpszNewFile,;
 INTEGER fFailIfExists,;
 INTEGER dwFlagsAndAttributes,;
 INTEGER dwFlags,;
 INTEGER dwContext
*
DECLARE INTEGER FtpDeleteFile IN WININET.DLL ;
 INTEGER nFile,;
 STRING  lpszFileName
*
DECLARE INTEGER InternetWriteFile IN WININET.DLL;
 INTEGER   hFile,;
 STRING  @ sBuffer,;
 INTEGER   lNumBytesToWrite,;
 INTEGER @ dwNumberOfBytesWritten
*
DECLARE INTEGER FtpOpenFile IN WININET.DLL;
 INTEGER hFtpSession,;
 STRING  sFileName,;
 INTEGER lAccess,;
 INTEGER lFlags,;
 INTEGER lContext

 

CLEAR
*DO UPLOAD_FTP
*DO DOWNLOAD_FTP
*DO DELETE_FTP
'FINISHED'

 

PROCEDURE UPLOAD_FTP
IF connect2ftp (ftp_ip, ftp_user, ftp_pass)
 lnFiles = ADIR (arr, vcLocalDir + vcFilename)
 FOR lnCnt=1 TO lnFiles
  lcSource = vcLocalDir + LOWER (arr [lnCnt, 1])
  lcTarget = vcServerDir + LOWER (arr [lnCnt, 1])
   local2ftp (hFtpSession, lcSource, lcTarget)
 ENDFOR
 = InternetCloseHandle (hFtpSession)
 = InternetCloseHandle (hOpen)
ENDIF
RETURN

PROCEDURE DOWNLOAD_FTP
sAgent = "vfp6"
sProxyName = CHR(0)
sProxyBypass = CHR(0)
lFlags = 0
hOpen = InternetOpen (sAgent, INTERNET_OPEN_TYPE_DIRECT, sProxyName, sProxyBypass, lFlags)
IF hOpen = 0
 RETURN
ENDIF
hFtpSession = InternetConnect (hOpen, ftp_ip, INTERNET_INVALID_PORT_NUMBER, ftp_user, ftp_pass, INTERNET_SERVICE_FTP, 0, 0)
IF hFtpSession = 0
 = InternetCloseHandle (hOpen)
 RETURN
ENDIF
lpszRemoteFile = vcServerDir+vcFilename
lpszNewFile    = vcLocalDir+vcFilename
fFailIfExists  = 0
dwContext      = 0
lnResult = FtpGetFile (hFtpSession, lpszRemoteFile, lpszNewFile, fFailIfExists, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_ASCII, dwContext)
= InternetCloseHandle (hFtpSession)
= InternetCloseHandle (hOpen)
RETURN

PROCEDURE DELETE_FTP
sAgent = "vfp6"
sProxyName = CHR(0)
sProxyBypass = CHR(0)
lFlags = 0
hOpen = InternetOpen (sAgent, INTERNET_OPEN_TYPE_DIRECT, sProxyName, sProxyBypass, lFlags)
IF hOpen = 0
 RETURN
ENDIF
hFtpSession = InternetConnect (hOpen, ftp_ip, INTERNET_INVALID_PORT_NUMBER, ftp_user, ftp_pass, INTERNET_SERVICE_FTP, 0, 0)
IF hFtpSession = 0
 = InternetCloseHandle (hOpen)
 RETURN
ENDIF
lpszRemoteFile = vcServerDir+vcFilename
lpszNewFile    = vcLocalDir+vcFilename
fFailIfExists  = 0
dwContext      = 0
lnResult = FtpDeleteFile (hFtpSession, lpszRemoteFile)
= InternetCloseHandle (hFtpSession)
= InternetCloseHandle (hOpen)
RETURN

FUNCTION connect2ftp (strHost, strUser, strPwd)
hOpen = InternetOpen ("vfp", 1, 0, 0, 0)
IF hOpen = 0
  "Sem acceso a WinInet.Dll"
 RETURN .F.
ENDIF
hFtpSession = InternetConnect (hOpen, strHost, 0, strUser, strPwd, 1,0,0)
IF hFtpSession = 0
 = InternetCloseHandle (hOpen)
 RETURN .F.
ENDIF
RETURN .T.

FUNCTION local2ftp (hConnect, lcSource, lcTarget)
hSource = FOPEN (lcSource)
IF (hSource = -1)
 RETURN -1
ENDIF
hTarget = FtpOpenFile(hConnect, lcTarget, GENERIC_WRITE, 2, 0)
IF hTarget = 0
 = FCLOSE (hSource)
 RETURN -2
ENDIF
lnBytesWritten = 0
lnChunkSize =  128
DO WHILE !FEOF(hSource)
 lcBuffer = FREAD (hSource, lnChunkSize)
 lnLength = Len(lcBuffer)
 IF lnLength<>0
  IF InternetWriteFile (hTarget, @lcBuffer, lnLength, @lnLength) = 1
   lnBytesWritten = lnBytesWritten + lnLength
  ELSE
   EXIT
  ENDIF
 ELSE
  EXIT
 ENDIF
ENDDO
= InternetCloseHandle (hTarget)
= FCLOSE (hSource)
RETURN lnBytesWritten



Answer this question

FTP with VFP

  • JVled

    Since you pointed that line in my direction i put some thought into this and remembered something to do with ASCII and binary protocols in FTP and tried changing that.

    I switched
    DEFINE FTP_TRANSFER_TYPE_ASCII
    for
    DEFINE FTP_TRANSFER_TYPE_BINARY

    and the problem was solved!!!


    But thanks a lot for you help Stuart! I was going on and on over this for days now! I don't think i would ever spot that line in particular. Smile

  • RMarmion

    Hi Miguel

     Miguel Angelo wrote:

    I can upload a file to the server with no problem, i check the file size and all is OK. If i download that file using an FTP program the file is downloaded with no problem. If i use this code to download that same file the file size increases!
    From that i can conclude that the problem is not in the upload part of the code.

    lnResult = FtpGetFile (hFtpSession, lpszRemoteFile, lpszNewFile, fFailIfExists, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_ASCII, dwContext)



    Try that line without the FTP_TRANSFER_TYPE_ASCII flag.

    Cheers

    Stuart

  • FTP with VFP