BBC BASIC for Windows
Programming >> Communication and Input/Output >> Uploading to FTP Server
http://bb4w.conforums.com/index.cgi?board=communication&action=display&num=1338486512

Uploading to FTP Server
Post by pettit on May 31st, 2012, 5:48pm

I have been attempting to use the code helpfully provided by Richard Russell in March 2010 "Uploading files to an FTP server".

http://bb4w.wikispaces.com/page/diff/Uploading+files+to+an+FTP+server/276699766

... and it very nearly works for me but not quite, and I can not fathom out why. The process seems to time out at the final stage. Connection is made and a file of the approriate name placed on the FTP server, however on performing

SYS `FtpPutFile`, hConnection%, source$, destination$, FTP_TRANSFER_TYPE_BINARY, 0 TO res%

after about 10.5 seconds the result 0 for res% is returned and the file on the server contains no data. source$ is a small 16Kb file.

This has happened with identical result on 2 different web hosts (PlusNet & Heart Internet). I experience no problems using FTP clients such as Cute FTP. Operating system WinXP Pro SP3.

Any ideas what might be causing the process to stall ?


Re: Uploading to FTP Server
Post by admin on May 31st, 2012, 10:05pm

on May 31st, 2012, 5:48pm, pettit wrote:
Any ideas what might be causing the process to stall ?

No, but the docs for FtpPutFile say 'To get a specific error message, call GetLastError':

http://msdn.microsoft.com/en-us/library/windows/desktop/aa384170.aspx

So if you haven't already done so I would advise calling GetLastError to see whether it sheds any light on why the call is failing. The BB4W docs tell you how:

http://www.bbcbasic.co.uk/bbcwin/manual/bbcwine.html#getlasterror

Richard.
Re: Uploading to FTP Server
Post by pettit on Jun 1st, 2012, 2:01pm

Thanks Richard. I have explored as you have suggested, and I am not sure I am attempting to display the error message correctly.

I have inserted the code defining the GetLastError function, and attempted to let error$=FNwinerror, but error$ afterwards is a null string. If I'm not doing this correctly, please let me know.

Nevertheless on inspection I find that winerr% returns a value of 12002, which perhaps unsurprisingly I see from the MS documentation is: ERROR_INTERNET_TIMEOUT - "The request has timed out."

Hmmm, I had already rather suspected this and was hoping to find out why.

I have tried the same BBC Basic code on my laptop (XP Home SP3), with virtually identical result except it takes twice as long to time out as measured using the TIME pseudo-variable, and winerr% returns 12003: ERROR_INTERNET_EXTENDED_ERROR - "An extended error was returned from the server. This is typically a string or buffer containing a verbose error message. Call InternetGetLastResponseInfo to retrieve the error text."

Does this help ? Are we closer to understanding why, despite the connection being clearly established, the transfer does not succeed ?

Re: Uploading to FTP Server
Post by admin on Jun 1st, 2012, 4:51pm

on Jun 1st, 2012, 2:01pm, pettit wrote:
I have inserted the code defining the GetLastError function, and attempted to let error$=FNwinerror, but error$ afterwards is a null string.

Strange. Sometimes FNwinerror returns "The operation completed successfully", when you know perfectly well it didn't, but returning an empty string is a new one on me.

Quote:
"An extended error was returned from the server. This is typically a string or buffer containing a verbose error message. Call InternetGetLastResponseInfo to retrieve the error text."

I suppose the next step is to call InternetGetLastResponseInfo as it suggests, in case that contains some useful diagnostic information:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa384717.aspx

Richard.
Re: Uploading to FTP Server
Post by pettit on Jun 1st, 2012, 5:43pm

Thanks again. I have looked at the InternetGetLastResponseInfo function, but feel I am beginning to get rather out of my depth trying to convert it into a BB4W SYS call to retrieve whatever useful information it might provide. I could certainly have an attempt, but the concern would be if it didn't work I wouldn’t know is it was my poor translation of code or merely another unhelpful response from Windows. Any assistance would be appreciated.

Just a thought, I was wondering whether your original code still functions in your own hands, lest impacting changes to dll libraries have since been distributed by Microsoft. Confirmation would be encouraging.

Re: Uploading to FTP Server
Post by admin on Jun 1st, 2012, 9:54pm

on Jun 1st, 2012, 5:43pm, pettit wrote:
I have looked at the InternetGetLastResponseInfo function, but feel I am beginning to get rather out of my depth trying to convert it into a BB4W SYS call

This should work:

Code:
      DEF FNlastresponseinfo
      LOCAL bufferlength%, buffer%, wininet%, iglri%, dwerror%
      bufferlength% = 255
      DIM buffer% LOCAL bufferlength%
      SYS "LoadLibrary", "WININET.DLL" TO wininet%
      SYS "GetProcAddress", wininet%, "InternetGetLastResponseInfoA" TO iglri%
      SYS iglri%, ^dwerror%, buffer%, ^bufferlength%
      SYS "FreeLibrary", wininet%
      = $$buffer% 

Quote:
Just a thought, I was wondering whether your original code still functions in your own hands

Yes, my 'uploadftp' program works fine.

For my interest, is the file you are attempting to upload an ASCII file or a binary file, and have you been careful to select the appropriate transfer type (FTP_TRANSFER_TYPE_ASCII or FTP_TRANSFER_TYPE_BINARY)?

Richard.
Re: Uploading to FTP Server
Post by pettit on Jun 2nd, 2012, 08:30am

The small file I am now using with 'ftpupload' is a simple 645 byte (tab delimited) ASCII text file terminated with 0d 0a. I have tried both ASCII and BINARY transfer types with identical outcome.

Thanks for the code to call InternetGetLastResponseInfo, much appreciated. Unfortunately the message yielded when called immediately after the 'FtpPutFile' SYS call is perhaps less than helpful; for ASCII transfer:

'200 Type set to A
200 PORT command successful
'

and for BINARY

'200 Type set to I
200 PORT command successful
'

(My single quotes) If I call GetLastError after rather than before InternetGetLastResponseInfo then the reported code & message are 0 and 'The operation completed successfully', as I guess would be expected.

I am certainly no expert, but is this is beginning to look like an issue concerning interaction with both my 2 different web hosts (PlusNet & Heart Internet) ? Any idea where we can go from here ?

Re: Uploading to FTP Server
Post by admin on Jun 2nd, 2012, 08:58am

on Jun 2nd, 2012, 08:30am, pettit wrote:
Any idea where we can go from here ?

To extract more diagnostic information is probably going to need a packet analyzer, so you can monitor exactly the network traffic flowing between your PC and the FTP server. You should then be able to see any unexpected responses (or lack of response!).

You might want to try something like Wireshark:

http://www.wireshark.org/

I presume you find that other FTP clients work correctly, in which case the likelihood is that there's a problem with FtpPutFile. As I expect you're aware, you can do the file transfer at a lower level, in much the same way as the alternative, more complex, PROCurldownload() does here:

http://bb4w.wikispaces.com/Downloading+a+file+from+a+URL

I haven't had to write the equivalent for uploading, but it's certainly possible and would give you more control over exactly what is happening.

Richard.
Re: Uploading to FTP Server
Post by admin on Jun 2nd, 2012, 09:06am

on Jun 2nd, 2012, 08:30am, pettit wrote:
Any idea where we can go from here ?

One further thought. Some FTP servers require using passive mode, so have you tried setting that in the InternetConnect call:

Code:
SYS `InternetConnect`, hOpen%, "ServerName", FTP_PORT, \
      \       "Username", "Password", SERVICE_FTP, _INTERNET_FLAG_PASSIVE, 0 \
      \       TO hConnection%
 

(use the Add Windows Constants utility to declare the constant).

Richard.
Re: Uploading to FTP Server
Post by pettit on Jun 2nd, 2012, 1:37pm

Richard your 'further thought' was a gem.

Success !

Setting passive mode in the InternetConnect call as you describe was indeed the solution. Once this SYS call was amended, the Add Windows Constants utility added the line _INTERNET_FLAG_PASSIVE = &8000000 to the BB4W code and all is now well.

Many thanks for your help.