Page 1 of 2

FTP Get File help

Posted: Wed Nov 02, 2011 12:56 pm
by Musco
I have been working on a project with the goal of accessing an FTP server and downloading files to update various devices, as well as the Netburner itself. The trouble I am running in to is when I try to download the file from the server. I start off by establishing a connection with the FTP server, followed by the FTPGetFileNames function (which works). Upon using the FTPGetFile function, the return value is -4 (COMMANDFAIL or COMMANDERROR). Any insight would be much appreciated as to what causes this error return value.

Re: FTP Get File help

Posted: Wed Nov 02, 2011 1:09 pm
by rnixon
Is this with the FTP client example code?

Re: FTP Get File help

Posted: Wed Nov 16, 2011 12:54 pm
by Musco
My apologies for not responding earlier. I am running a custom program with FTP client functionality. I was able to fix the problems I was receiving with the error codes. I have hit another bump in the road. I can download the bin file to the netburner but now I would like to save it to the on board flash file system. I have reviewed the EFFS-STD example and went ahead and allocated enough flash memory for the file system. Now I would like to take the input stream data received from the FTPGetFile function and store it into a file.

Re: FTP Get File help

Posted: Fri Nov 18, 2011 11:05 am
by Musco
Update:

I have been taking the following steps to find a possible solution:
1. Establish FTP connection and use FTPGetFile to get file from FTP server.
2. In order to read returned FD from FTPGetFile, I use a similar function to that of FTPD_GetFileFromClient from ftp_f.cpp in example EFFS-STD-HTTP.
3. Write buffer that FD was read into to a file in the file system.

When using ReadWithTimeout, it looks to have read the entire FD then returns -1. What type of failure causes this return value? Any help would be much appreciated, thanks!

Re: FTP Get File help

Posted: Fri Nov 18, 2011 2:41 pm
by greengene
if i'm understanding what you're doing, you are trying to read a file stored in
the effs file system by using ReadWithTimeout() - that's not gonna work.

to read/write the EFFS files, you need to use the EFFS commands, e.g.,
fs_read()/fs_write().

Re: FTP Get File help

Posted: Mon Nov 21, 2011 6:55 am
by Musco
Thanks for the response.

What I am trying to read with ReadWithTimeout() is the file descriptor returned from the FTPGetFile function. After reading that into a buffer, I will then write it to a file in the file system using fs_write. I'm assuming this is the easiest way to get a file from an FTP site stored in the netburner's file system but if I'm wrong, please point me in the right direction.

Re: FTP Get File help

Posted: Mon Nov 21, 2011 9:02 am
by greengene
ok, i was assuming the worst, but it looks like you are almost there.
i expect that the return code of -1 is EOF on trying to read past the
end of file. so as in the example, return > 0 is byte count, 0 is timeout,
and an unspecified -1 appear to be the standard EOF.
i'd just go with that since it appears to be working.

Re: FTP Get File help

Posted: Tue Nov 22, 2011 12:12 pm
by Musco
I still can't quite figure out why the read returns -1. I'm using code copied directly from the EFFS-STD-HTTP example. The GetFileFromClient() function does almost exactly what i want to do except in my case, the Netburner is acting as the FTP client and receiving a file from an FTP server. Here is the code I am using to read the file descriptor returned from FTPGetFile() and then write to a file in the netburner's flash file system.


Code: Select all

#define FTP_BUFFER_SIZE  ( 500 * 1024 )
static char FTP_buffer[FTP_BUFFER_SIZE] __attribute__( ( aligned( 16 ) ) );


	int ftp = FTP_InitializeSession( AsciiToIp( SERVER_IP_ADDR ),
	                                        FTP_PORT,
	                                        USER,
	                                        PASS,
	                                        200 );

    if ( ftp > 0 ) // if the var ftp is > 0, it is the session handle
    {

		int fd = FTPGetFile(ftp, fileName, TRUE, 5 * TICKS_PER_SECOND);
		if(fd > 0)
		{
			wfile = fs_open( fileName, "w+" );

			int bytes_read;
			int bytes_written;
			int retry;
			int FtpBufIndex = 0;  // position in buffer
			   /* This loop will read the file data from the client, accumulate
			    * data until FTP_BUFFER_SIZE is reached, then write the data to
			    * flash in one write.
			    */
			   do
			   {
			      bytes_read = ReadWithTimeout( fd, FTP_buffer + FtpBufIndex,
			    		                        FTP_BUFFER_SIZE - FtpBufIndex,
			    		                        TICKS_PER_SECOND * 20 );
			      iprintf("Bytes read: %d\r\n", bytes_read );

			      if ( bytes_read > 0 )
			      {
			    	 FtpBufIndex += bytes_read;
			         iprintf( "FtpBufIndex: %d\r\n", FtpBufIndex );
			      }

			      if ( FtpBufIndex == FTP_BUFFER_SIZE )
			      {
			         bytes_written = 0;
			         retry = 0;
			         do {
			            //  buffer, size of item, number of items, file handle
			        	bytes_written = fs_write( FTP_buffer, 1, FtpBufIndex, wfile );
			        	iprintf("bytes_written: %d\r\n", bytes_written);

			            if ( bytes_written < FtpBufIndex )
			            {
			               iprintf("Retry: %d\r\n", retry);
			               OSTimeDly( TICKS_PER_SECOND / 4 );
			               retry++;
			            }
			         } while ( (bytes_written < FtpBufIndex) && ( retry < 10 ) );

			         FtpBufIndex = 0;
			      }
			   }  while ( ( bytes_read > 0 ) && ( retry < 10 ) );

			   if ( retry >= 10 )
			   {
			      iprintf("Error - could not write file: %s\r\n", file_name);
			      do {
			         bytes_read = ReadWithTimeout( fd, FTP_buffer, FTP_BUFFER_SIZE, TICKS_PER_SECOND * 2 );
			         //iprintf("Bytes read: %d\r\n", bytes_read );
			      } while ( bytes_read > 0 );

			      fs_close( wfile );
			      fs_delete( file_name );
			      return ( FTPD_FAIL );
			   }

			   iprintf("FtpBufIndex: %d\r\n", FtpBufIndex);
			   if ( FtpBufIndex )
			   {
			      bytes_written = fs_write( FTP_buffer, 1, FtpBufIndex, wfile );
			      iprintf( "wrote %d bytes\r\n", bytes_written );
			      if ( bytes_written < FtpBufIndex )
			      {
			         iprintf("Error - could not write file: %s\r\n", file_name);
			         do {
			            bytes_read = ReadWithTimeout( fd, FTP_buffer, FTP_BUFFER_SIZE, TICKS_PER_SECOND * 2 );
			            //iprintf("Bytes read: %d\r\n", bytes_read );
			         } while ( bytes_read > 0 );
			         fs_close( wfile );
			         fs_delete( file_name );
			         return ( FTPD_FAIL );
			      }
			   }

			   fs_close( wfile );
			   return( FTPD_OK );
		}
    }

Re: FTP Get File help

Posted: Tue Nov 22, 2011 1:18 pm
by rnixon
Saw this on the ftp get manual page, but not sure if it is the cause of the prob you are having:

Important: After the file descriptor has been returned, you must call the FTPGetCommandResult function to get the result from the read. Warning: Failing to do this will cause the system to get out of sync. A return value of 226 is normal.

Re: FTP Get File help

Posted: Tue Nov 22, 2011 1:31 pm
by Musco
Oops I forgot to include that part of my code in the post... I do call that function after trying to read the file descriptor.

Code: Select all

			
close(fd);

rv = FTPGetCommandResult( ftp, tmp_resultbuff, 255, 5 * TICKS_PER_SECOND );
if ( rv != 226 )
{

sprintf(buffer,"\n\r1Error Command result = %d %s\r\n",rv,tmp_resultbuff);
writestring(fdDebugSerial,buffer);

}

}

I forgot to mention that the file I am trying to get using FTPGetFile() is a binary file with size about 131,000 bytes. I tested the same code using a 35 byte text file instead and it worked perfectly.