Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

I'm trying to copy a file from my c

Status
Not open for further replies.

Steve Meyerson

Programmer
Sep 17, 2020
320
US
I'm trying to copy a file from my computer to my web host's server using FtpPut.prg (shown below for reference).

The debugger with SET STEP ON shows the connection is made ok but the transfer fails at
Code:
   IF FtpPutFile(hftpSession, lcSource,;
         lcTarget, lnXFerType, 0) = 1
      WAIT WINDOW lcSource + ' transferred.' TIMEOUT 2
   ENDIF

My aim is to transfer files in my VFP9 program (exe) as simple (and fast) as possible without additional installation(s) required by the users. Most files will be pdf's (.5-1 MB). I would appreciate any help. TIA.

Steve

Code:
*... FTPPut.PRG ...*

*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
*.................................................................................
set step on
************** My parameters
lcHost     = 'gator4247.hostgator.com'
lcUser     = 'smeyerson'
lcPassword = 'MyPasswordxxx'
lcSource   = 'e:\TextFile.txt'
lcTarget   = '/home2/smeyerson/MyFolder'

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 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)
lnXFerType = 1

IF connect2ftp (lcHost, lcUser, lcPassword)
   WAIT WINDOW 'Transferring....' NOWAIT
   IF FtpPutFile(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 ****************************
 
Gerrit,

Thanks for the link. I think the "portable" version is the exact same exe file as the full installation. It seems to run the same by itself.

Steve
 
What do I mean with FTP root folder? Not the Linux root dorectory nor Windows C:, just a root directory.

If you manually use WinSCP or FileZilla, when you connect to the FTP server, you start in some directory that the hoster (hostgator) has set up for the FTP user. You can upload there with just the file name. You can try and upload to ..\..\something\filename.txt, but usually the FTP user can only upload to the FTP root directory or subfolders of that. And for internet hosting, well, the webroot (aka htdocs folder in an Apache installation) is below the FTP root, as some files like error log, access log, etc. should be available to you by FTP access but for privacy reasons never be accessible from the web.

So root directories are a very common term for some base folder. Hostgator will never give you access to the Linux root directory /.

As far as I posted my tests the subfolder needs to be specified by ./subfolder, and be assured, in my case the hosted server also is a Linux server. If I remember correctly you tried with an absolute path and hostgator confirmed you that this is the way to go with their hosting, especially that you should only provide the path, not a file name. On the other side I showed you how Microsoft defines the target file parameter and I said whatever is the truth in FTP commands, you don't use an FTP command when you use FtpPutFile, yyou use an API function of the Wininet.dll and that certainly uses FTP commmands. It has made the connection and in that moment also exchanged some informartion that enables it do do the right things in terms of the native FTP commands it sends via the connection it has established.

I don't know what stilll hinders you to test this. Simply set the lcTarget to just the file name and run your code, the worst thing that could happen is an error, you donÄt brek the server with any FTP upload, even if the file might go where you don't want it, this will tell you what the current directory is after you have the connection.

To be clear: Do this in parallel with a manual FTP session with WinSCP or any FTP client you're familiar with, after you execute an FTP upload in VFP without error don't forget the FTP client will need to refresh the directory it displays, and then you'll very likely see the uploaded file.

Chriss
 
Code:
lcSource   = "E:\TextFile.txt"
lcTarget   = "/MyFolder/OtherName.txt"  && Under the "root"

Chris, I think I finally got it! As you said, Putting the lcTarget file name without path sends the file to the root folder on the server (/home2/smeyerson).

When I prefaced lcTarget file with the full server path (/home2/smeyerson/MyFolder/), the transfer fails. I tried many combinations to put the file in subfolder (/MyFolder/.

It finally went to the subfolder when I prefaced the lcTarget file with ONLY the subfolder name WITHOUT the root as in the code above.

Now I'll work on FtpGet. Thanks again for your help!

Steve
 
I used ./ to start the relative path as in ./MyFolder/Othername.txt, but I now tried without the dot and that works, too. I still think it's good practice to add it to distinguish it from a full path. As in Linux, there aren't drive letters, just mount points. So relative paths are not necessarily distinguishable from full paths when not prefixed with a dot. It's just a small not very important detail.

By he way, the Wininet FTP solution does really only do FTP, not FTPS. When I use FileZilla and it's set up to use FTP over TLS (which is FTPS), that can be seen from a network monitor, while the VFP code transfers the data but more important even the password as plaintext.

So there is one advantage of using an FTP client that supports secured file transfers and can be automated at least with command line options.

Chriss
 
Good points, Chris. Took me a while to digest it all, but I'm getting there (I think).

So far as the command line option, some of my command lines end up over 255 chars. I tried to break them into 2 commands, but I haven't been able to make that work, so I'll stick with Winnet. No problem.

Question: I will be transferring over 100 files in loops. Can I issue the DECLARE statements just one time before the loop(s) and the transfer statements inside the loop?

Steve


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top