Native ftp client example

Discussion related to the Cross Codebot open source framework
sysrpl
Posts: 108
Joined: Thu Feb 05, 2015 6:31 pm

Native ftp client example

Postby sysrpl » Sun Apr 05, 2015 8:00 pm


The Cross Codebot library provides a friendly and easy to use native ftp client protocol implementation. Native in that it uses sockets to implement an ftp client which works across all platforms with no external dependencies.

To use the ftp client (example project located here) you simply add the codebot package to your program requirements. You can do this using the project inspector.



Then add Codebot.Networking.Ftp to your uses clause, create an instance of of a TFtpClient and fill out any pertinent information, such as the host name/user name/password, before calling connect.

Here's a example:

program ftptest;

{$mode delphi}
{$apptype console}

uses
Codebot.Networking.Ftp;

var
FtpClient: TFtpClient;
begin
{ Create an ftp client object }
FtpClient := TFtpClient.Create;
try
{ Provide the host name of the ftp server }
FtpClient.Host := 'ftp.cs.brown.edu';
{ Attempt to connect }
if FtpClient.Connect then
WriteLn('Connected to the brown university ftp server')
else
WriteLn('Failed to connect to the brown university ftp server');
finally
{ Free the ftp client object }
FtpClient.Free;
end;
{ And we're done }
WriteLn('done.');
ReadLn;
end.

Output:

Connected to the brown university ftp server
done.

Note that the example outputs text to the terminal and that no user name or password was specified. The default user name is anonymous and password is a blank email address. To change these values set FtpClient.UserName or FtpClient.Password before invoking Connect.

Going further, you may want to use the ftp client to list folder and files. TFtpClient has two methods you can use to to accomplish this task, FileList, and FindFirst. The first method FileList returns a text listing of the folders and files in the current directory. Consider this minor modification to the original example:

if FtpClient.Connect then
begin
WriteLn('Connected to the brown university ftp server');
WriteLn(FtpClient.FileList);
end
else
WriteLn('Failed to connect to the brown university ftp server');

Output:

Connected to the brown university ftp server
drwxrwxr-t 2 0 0 65536 May 27 2013 incoming
drwxr-xr-x 33 0 2 8192 Aug 13 2013 pub
drwxr-xr-x 51 0 2 8192 Dec 11 2012 u

done.

The FileList method take an optional path argument where you can specify which directory to list folder an files. If the path argument is omitted the current directory is listed. To change the working directory use the ChangeDir method:

if FtpClient.Connect then
begin
WriteLn('Connected to the brown university ftp server');
{ Attempt to change to the pub folder }
if FtpClient.ChangeDir('pub') then
begin
{ And request a file list }
WriteLn(FtpClient.FileList);
{ As well as the file list of the parent folder }
WriteLn(FtpClient.FileList('../'));
end;
end
else
WriteLn('Failed to connect to the brown university ftp server');

Truncated output:

-rw-r--r-- 1 60001 2 276928 Aug 13 1991 tmm.tar.Z
-rw-r--r-- 1 0 2 357253 Jul 12 1993 tn3270.tar.Z
drwxr-xr-x 2 2546 1030 8192 Sep 18 1998 widgetlib
drwxr-xr-x 2 7500 2 8192 Sep 8 2000 xmx
-rw-r--r-- 1 2128 2 182227 Apr 14 1994 zone.tar.Z

drwxrwxr-t 2 0 0 65536 May 27 2013 incoming
drwxr-xr-x 33 0 2 8192 Aug 13 2013 pub
drwxr-xr-x 51 0 2 8192 Dec 11 2012 u

done.

This is all good, both it's a bit awkward to parse the text results of FileList and that is where the FindFirst method to list folders and files comes into play. To use FindFirst you supply a path, and optional attribute flags and in return you receive a TRemoteFindData structure defined as follows:

type
TRemoteFindData = record
{ Path to the file }
Path: string;
{ Name of the remote item }
Name: string;
{ Modified date of the remote item }
Date: TDateTime;
{ Size in bytes of the remote item }
Size: LargeWord;
{ Attributes describing the remote item }
Attributes: TFileSystemAttributes;
end;

Here's an example demonstrating how you use FindFirst paired with FindNext. Note there is no need for a FindClose like method:

if FtpClient.Connect then
begin
WriteLn('Connected to the brown university ftp server');
{ List items in pub with ending with .Z }
Success := FtpClient.FindFirst('pub/*.Z', FindData);
{ Continue iteration while matches are found }
while Success do
begin
{ Write out the file details }
WriteLn('file ', FindData.Name, ' ', FindData.Size, ' bytes');
{ And find the next match }
Success := FtpClient.FindNext(FindData);
end;
end
else
WriteLn('Failed to connect to the brown university ftp server');

Truncated output:

file pub/sphigs.tar.Z 261154 bytes
file pub/srgp.tar.Z 371225 bytes
file pub/tango.tar.Z 584376 bytes
file pub/tconsole.tar.Z 21342 bytes
file pub/threads.tar.nostdio.Z 199829 bytes
file pub/tmm.tar.Z 276928 bytes
file pub/tn3270.tar.Z 357253 bytes
file pub/zone.tar.Z 182227 bytes
done.


Next you may want to try sending or receiving files to or from a server. To send a file use the FilePut method, to receive a file use the FileGet method. Here is an example which receives a README file:

if FtpClient.Connect then
begin
WriteLn('Connected to the brown university ftp server');
{ Attempt to get the remote pub/README file }
if FtpClient.FileGet('pub/README', 'README') then
{ And display its contents }
WriteLn(Codebot.System.FileReadStr('README'));
end
else
WriteLn('Failed to connect to the brown university ftp server');

Truncated output:

zone.tar.Z An extension to the PostScript language for 3D
special effects and programming.
#------------------------------------------------------------------------
# Mailing lists
#------------------------------------------------------------------------
# bwe, field and related tools:
# QUESTIONS: bwe at cs.brown.edu
# ADD/REMOVE: spr at cs.brown.edu
# POST: field at cs.brown.edu
#
# hyperbole:
# ADD/REMOVE: hyperbole-request at hub.ucsb.edu
# POST: hyperbole at hub.ucsb.edu
#------------------------------------------------------------------------
# Send comments and questions about this archive to redsoft at cs.brown.edu.

done.

Below is a full list of the methods and properties of TFtpClient. Given the examples above and the comments below using other methods of TFtpClient should be quite easy for users to pick up on and reuse.

{ Attempt to open a file transfer connection using the host, port, username, and password }
function Connect: Boolean;
{ Close any opened connection }
procedure Disconnect;
{ Cancel any ongoing transfers }
procedure Cancel;
{ Returns the current remote directory }
function GetCurrentDir: string;
{ Returns true if a remote directory exists }
function DirExists(const Dir: string): Boolean;
{ Change to a new current remote directory }
function ChangeDir(const Dir: string): Boolean;
{ Create a new remote directory }
function MakeDir(const Dir: string): Boolean;
{ Delete an existing remote directory }
function RemoveDir(const Dir: string): Boolean;
{ Delete an existing remote file }
function FileDelete(const FileName: string): Boolean;
{ Returns true if a remote file exists }
function FileExists(const FileName: string): Boolean;
{ Rename a remote file, works with directories too }
function FileRename(const OldName, NewName: string): Boolean;
{ Retrieve the size of a remote file }
function FileSize(const FileName: string): LargeWord;
{ Retrieve the modified date of a remote file }
function FileDate(const FileName: string): TDateTime;
{ Initiate an file upload to the remote server }
function FilePut(const LocalFile, RemoteFile: string; Overwrite: Boolean = True): Boolean;
{ Request a file download from the remote server }
function FileGet(const RemoteFile, LocalFile: string; Overwrite: Boolean = True): Boolean;
{ Retrieve a text mode listing files and folders }
function FileList(const Path: string = ''): string;
{ Initiate a structured listing files and folders with an optional attribute mask }
function FindFirst(const Path: string; out FindData: TRemoteFindData;
Allow: TFileSystemAttributes = fsaAny): Boolean;
{ Continue with the next listing started by FindFirst }
function FindNext(out FindData: TRemoteFindData): Boolean;
{ Returns true when connected to a remote server, otherwise acts like connect and disconnect }
property Connected: Boolean;
{ The name of the host to resolve when connecting }
property Host: string;
{ The port used for issuing ftp commands, defaults to 21 }
property Port: Word;
{ The username used when connecting, defaults to anonymous }
property UserName: string read FUserName write FUserName;
{ The password used when connecting, defaults to an email address }
property Password: string;
{ An event invoked echoing ftp commands issued by the client }
property OnCommand: TTextEvent;
{ An event invoked when responses are read from the remote server }
property OnResponse: TTextEvent;
{ An event continuously invoked as file transfers occur }
property OnProgress: TTransmitEvent;

Return to “Cross Codebot”

Who is online

Users browsing this forum: No registered users and 1 guest