在Delphi 7开发下有强大的Indy控件,版本为9,要实现一个FTP服务器,参考自带的例子,发现还要写很多函数,而且不支持中文显示文件列表等等。于是,自己改进封装了下,形成一个TFTPServer类,源码如下:
- {*******************************************************}
- { }
- { 系统名称 FTP服务器类 }
- { 版权所有 (C) http://blog.csdn.net/akof1314 }
- { 单元名称 FTPServer.pas }
- { 单元功能 在Delphi 7下TIdFTPServer实现FTP服务器 }
- { }
- {*******************************************************}
- unit FTPServer;
- interface
- uses
- Classes, Windows, Sysutils, IdFTPList, IdFTPServer, Idtcpserver, IdSocketHandle, Idglobal, IdHashCRC, IdStack;
- {-------------------------------------------------------------------------------
- 功能: 自定义消息,方便与窗体进行消息传递
- -------------------------------------------------------------------------------}
- type
- TFtpNotifyEvent = procedure (ADatetime: TDateTime;AUserIP, AEventMessage: string) of object;
- {-------------------------------------------------------------------------------
- 功能: FTP服务器类
- -------------------------------------------------------------------------------}
- type
- TFTPServer = class
- private
- FUserName,FUserPassword,FBorrowDirectory: string;
- FBorrowPort: Integer;
- IdFTPServer: TIdFTPServer;
- FOnFtpNotifyEvent: TFtpNotifyEvent;
- procedure IdFTPServer1UserLogin( ASender: TIdFTPServerThread; const AUsername, APassword: string; var AAuthenticated: Boolean ) ;
- procedure IdFTPServer1ListDirectory( ASender: TIdFTPServerThread; const APath: string; ADirectoryListing: TIdFTPListItems ) ;
- procedure IdFTPServer1RenameFile( ASender: TIdFTPServerThread; const ARenameFromFile, ARenameToFile: string ) ;
- procedure IdFTPServer1RetrieveFile( ASender: TIdFTPServerThread; const AFilename: string; var VStream: TStream ) ;
- procedure IdFTPServer1StoreFile( ASender: TIdFTPServerThread; const AFilename: string; AAppend: Boolean; var VStream: TStream ) ;
- procedure IdFTPServer1RemoveDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ;
- procedure IdFTPServer1MakeDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ;
- procedure IdFTPServer1GetFileSize( ASender: TIdFTPServerThread; const AFilename: string; var VFileSize: Int64 ) ;
- procedure IdFTPServer1DeleteFile( ASender: TIdFTPServerThread; const APathname: string ) ;
- procedure IdFTPServer1ChangeDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ;
- procedure IdFTPServer1CommandXCRC( ASender: TIdCommand ) ;
- procedure IdFTPServer1DisConnect( AThread: TIdPeerThread ) ;
- protected
- function TransLatePath( const APathname, homeDir: string ) : string;
- public
- constructor Create; reintroduce;
- destructor Destroy; override;
- procedure Run;
- procedure Stop;
- function GetBindingIP():string;
- property UserName: string read FUserName write FUserName;
- property UserPassword: string read FUserPassword write FUserPassword;
- property BorrowDirectory: string read FBorrowDirectory write FBorrowDirectory;
- property BorrowPort: Integer read FBorrowPort write FBorrowPort;
- property OnFtpNotifyEvent: TFtpNotifyEvent read FOnFtpNotifyEvent write FOnFtpNotifyEvent;
- end;
- implementation
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.Create
- 功能: 创建函数
- 参数: 无
- 返回值: 无
- -------------------------------------------------------------------------------}
- constructor TFTPServer.Create;
- begin
- IdFTPServer := tIdFTPServer.create( nil ) ;
- IdFTPServer.DefaultPort := 21; //默认端口号
- IdFTPServer.AllowAnonymousLogin := False; //是否允许匿名登录
- IdFTPServer.EmulateSystem := ftpsUNIX;
- IdFTPServer.HelpReply.text := '帮助还未实现!';
- IdFTPServer.OnChangeDirectory := IdFTPServer1ChangeDirectory;
- IdFTPServer.OnGetFileSize := IdFTPServer1GetFileSize;
- IdFTPServer.OnListDirectory := IdFTPServer1ListDirectory;
- IdFTPServer.OnUserLogin := IdFTPServer1UserLogin;
- IdFTPServer.OnRenameFile := IdFTPServer1RenameFile;
- IdFTPServer.OnDeleteFile := IdFTPServer1DeleteFile;
- IdFTPServer.OnRetrieveFile := IdFTPServer1RetrieveFile;
- IdFTPServer.OnStoreFile := IdFTPServer1StoreFile;
- IdFTPServer.OnMakeDirectory := IdFTPServer1MakeDirectory;
- IdFTPServer.OnRemoveDirectory := IdFTPServer1RemoveDirectory;
- IdFTPServer.Greeting.Text.Text := '欢迎进入FTP服务器';
- IdFTPServer.Greeting.NumericCode := 220;
- IdFTPServer.OnDisconnect := IdFTPServer1DisConnect;
- with IdFTPServer.CommandHandlers.add do
- begin
- Command := 'XCRC'; //可以迅速验证所下载的文档是否和源文档一样
- OnCommand := IdFTPServer1CommandXCRC;
- end;
- end;
- {-------------------------------------------------------------------------------
- 过程名: CalculateCRC
- 功能: 计算CRC
- 参数: const path: string
- 返回值: string
- -------------------------------------------------------------------------------}
- function CalculateCRC( const path: string ) : string;
- var
- f: tfilestream;
- value: dword;
- IdHashCRC32: TIdHashCRC32;
- begin
- IdHashCRC32 := nil;
- f := nil;
- try
- IdHashCRC32 := TIdHashCRC32.create;
- f := TFileStream.create( path, fmOpenRead or fmShareDenyWrite ) ;
- value := IdHashCRC32.HashValue( f ) ;
- result := inttohex( value, 8 ) ;
- finally
- f.free;
- IdHashCRC32.free;
- end;
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1CommandXCRC
- 功能: XCRC命令
- 参数: ASender: TIdCommand
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1CommandXCRC( ASender: TIdCommand ) ;
- // note, this is made up, and not defined in any rfc.
- var
- s: string;
- begin
- with TIdFTPServerThread( ASender.Thread ) do
- begin
- if Authenticated then
- begin
- try
- s := ProcessPath( CurrentDir, ASender.UnparsedParams ) ;
- s := TransLatePath( s, TIdFTPServerThread( ASender.Thread ) .HomeDir ) ;
- ASender.Reply.SetReply( 213, CalculateCRC( s ) ) ;
- except
- ASender.Reply.SetReply( 500, 'file error' ) ;
- end;
- end;
- end;
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.Destroy
- 功能: 析构函数
- 参数: 无
- 返回值: 无
- -------------------------------------------------------------------------------}
- destructor TFTPServer.Destroy;
- begin
- IdFTPServer.free;
- inherited destroy;
- end;
- function StartsWith( const str, substr: string ) : boolean;
- begin
- result := copy( str, 1, length( substr ) ) = substr;
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.Run
- 功能: 开启服务
- 参数: 无
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.Run;
- begin
- IdFTPServer.DefaultPort := BorrowPort;
- IdFTPServer.Active := True;
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.Stop
- 功能: 关闭服务
- 参数: 无
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.Stop;
- begin
- IdFTPServer.Active := False;
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.GetBindingIP
- 功能: 获取绑定的IP地址
- 参数:
- 返回值: string
- -------------------------------------------------------------------------------}
- function TFTPServer.GetBindingIP():string ;
- begin
- Result := GStack.LocalAddress;
- end;
- {-------------------------------------------------------------------------------
- 过程名: BackSlashToSlash
- 功能: 反斜杠到斜杠
- 参数: const str: string
- 返回值: string
- -------------------------------------------------------------------------------}
- function BackSlashToSlash( const str: string ) : string;
- var
- a: dword;
- begin
- result := str;
- for a := 1 to length( result ) do
- if result[a] = '/' then
- result[a] := '/';
- end;
- {-------------------------------------------------------------------------------
- 过程名: SlashToBackSlash
- 功能: 斜杠到反斜杠
- 参数: const str: string
- 返回值: string
- -------------------------------------------------------------------------------}
- function SlashToBackSlash( const str: string ) : string;
- var
- a: dword;
- begin
- result := str;
- for a := 1 to length( result ) do
- if result[a] = '/' then
- result[a] := '/';
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.TransLatePath
- 功能: 路径名称翻译
- 参数: const APathname, homeDir: string
- 返回值: string
- -------------------------------------------------------------------------------}
- function TFTPServer.TransLatePath( const APathname, homeDir: string ) : string;
- var
- tmppath: string;
- begin
- result := SlashToBackSlash(Utf8ToAnsi(homeDir) ) ;
- tmppath := SlashToBackSlash( Utf8ToAnsi(APathname) ) ;
- if homedir = '/' then
- begin
- result := tmppath;
- exit;
- end;
- if length( APathname ) = 0 then
- exit;
- if result[length( result ) ] = '/' then
- result := copy( result, 1, length( result ) - 1 ) ;
- if tmppath[1] <> '/' then
- result := result + '/';
- result := result + tmppath;
- end;
- {-------------------------------------------------------------------------------
- 过程名: GetNewDirectory
- 功能: 得到新目录
- 参数: old, action: string
- 返回值: string
- -------------------------------------------------------------------------------}
- function GetNewDirectory( old, action: string ) : string;
- var
- a: integer;
- begin
- if action = '../' then
- begin
- if old = '/' then
- begin
- result := old;
- exit;
- end;
- a := length( old ) - 1;
- while ( old[a] <> '/' ) and ( old[a] <> '/' ) do
- dec( a ) ;
- result := copy( old, 1, a ) ;
- exit;
- end;
- if ( action[1] = '/' ) or ( action[1] = '/' ) then
- result := action
- else
- result := old + action;
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1UserLogin
- 功能: 允许服务器执行一个客户端连接的用户帐户身份验证
- 参数: ASender: TIdFTPServerThread; const AUsername, APassword: string; var AAuthenticated: Boolean
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1UserLogin( ASender: TIdFTPServerThread;
- const AUsername, APassword: string; var AAuthenticated: Boolean ) ;
- begin
- AAuthenticated := ( AUsername = UserName ) and ( APassword = UserPassword ) ;
- if not AAuthenticated then
- exit;
- ASender.HomeDir := AnsiToUtf8(BorrowDirectory);
- asender.currentdir := '/';
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'用户登录服务器');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1ListDirectory
- 功能: 允许服务器生成格式化的目录列表
- 参数: ASender: TIdFTPServerThread; const APath: string; ADirectoryListing: TIdFTPListItems
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1ListDirectory( ASender: TIdFTPServerThread; const APath: string; ADirectoryListing: TIdFTPListItems ) ;
- procedure AddlistItem( aDirectoryListing: TIdFTPListItems; Filename: string; ItemType: TIdDirItemType; size: int64; date: tdatetime ) ;
- var
- listitem: TIdFTPListItem;
- begin
- listitem := aDirectoryListing.Add;
- listitem.ItemType := ItemType; //表示一个文件系统的属性集
- listitem.FileName := AnsiToUtf8(Filename); //名称分配给目录中的列表项,这里防止了中文乱码
- listitem.OwnerName := 'anonymous';//代表了用户拥有的文件或目录项的名称
- listitem.GroupName := 'all'; //指定组名拥有的文件名称或目录条目
- listitem.OwnerPermissions := 'rwx'; //拥有者权限,R读W写X执行
- listitem.GroupPermissions := 'rwx'; //组拥有者权限
- listitem.UserPermissions := 'rwx'; //用户权限,基于用户和组权限
- listitem.Size := size;
- listitem.ModifiedDate := date;
- end;
- var
- f: tsearchrec;
- a: integer;
- begin
- ADirectoryListing.DirectoryName := apath;
- a := FindFirst( TransLatePath( apath, ASender.HomeDir ) + '*.*', faAnyFile, f ) ;
- while ( a = 0 ) do
- begin
- if ( f.Attr and faDirectory > 0 ) then
- AddlistItem( ADirectoryListing, f.Name, ditDirectory, f.size, FileDateToDateTime( f.Time ) )
- else
- AddlistItem( ADirectoryListing, f.Name, ditFile, f.size, FileDateToDateTime( f.Time ) ) ;
- a := FindNext( f ) ;
- end;
- FindClose( f ) ;
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1RenameFile
- 功能: 允许服务器重命名服务器文件系统中的文件
- 参数: ASender: TIdFTPServerThread; const ARenameFromFile, ARenameToFile: string
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1RenameFile( ASender: TIdFTPServerThread;
- const ARenameFromFile, ARenameToFile: string ) ;
- begin
- try
- if not MoveFile( pchar( TransLatePath( ARenameFromFile, ASender.HomeDir ) ) , pchar( TransLatePath( ARenameToFile, ASender.HomeDir ) ) ) then
- RaiseLastOSError;
- except
- on e:Exception do
- begin
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'重命名文件[' + Utf8ToAnsi(ARenameFromFile) + ']失败,原因是' + e.Message);
- Exit;
- end;
- end;
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'重命名文件[' + Utf8ToAnsi(ARenameFromFile) + ']为[' + Utf8ToAnsi(ARenameToFile) + ']');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1RetrieveFile
- 功能: 允许从服务器下载文件系统中的文件
- 参数: ASender: TIdFTPServerThread; const AFilename: string; var VStream: TStream
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1RetrieveFile( ASender: TIdFTPServerThread;
- const AFilename: string; var VStream: TStream ) ;
- begin
- VStream := TFileStream.Create( translatepath( AFilename, ASender.HomeDir ) , fmopenread or fmShareDenyWrite ) ;
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'下载文件[' + Utf8ToAnsi(AFilename) + ']');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1StoreFile
- 功能: 允许在服务器上传文件系统中的文件
- 参数: ASender: TIdFTPServerThread; const AFilename: string; AAppend: Boolean; var VStream: TStream
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1StoreFile( ASender: TIdFTPServerThread;
- const AFilename: string; AAppend: Boolean; var VStream: TStream ) ;
- begin
- if FileExists( translatepath( AFilename, ASender.HomeDir ) ) and AAppend then
- begin
- VStream := TFileStream.create( translatepath( AFilename, ASender.HomeDir ) , fmOpenWrite or fmShareExclusive ) ;
- VStream.Seek( 0, soFromEnd ) ;
- end
- else
- VStream := TFileStream.create( translatepath( AFilename, ASender.HomeDir ) , fmCreate or fmShareExclusive ) ;
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'上传文件[' + Utf8ToAnsi(AFilename) + ']');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1RemoveDirectory
- 功能: 允许服务器在服务器删除文件系统的目录
- 参数: ASender: TIdFTPServerThread; var VDirectory: string
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1RemoveDirectory( ASender: TIdFTPServerThread;
- var VDirectory: string ) ;
- begin
- try
- RmDir( TransLatePath( VDirectory, ASender.HomeDir ) ) ;
- except
- on e:Exception do
- begin
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'删除目录[' + Utf8ToAnsi(VDirectory) + ']失败,原因是' + e.Message);
- Exit;
- end;
- end;
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'删除目录[' + Utf8ToAnsi(VDirectory) + ']');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1MakeDirectory
- 功能: 允许服务器从服务器中创建一个新的子目录
- 参数: ASender: TIdFTPServerThread; var VDirectory: string
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1MakeDirectory( ASender: TIdFTPServerThread;
- var VDirectory: string ) ;
- begin
- try
- MkDir( TransLatePath( VDirectory, ASender.HomeDir ) ) ;
- except
- on e:Exception do
- begin
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'创建目录[' + Utf8ToAnsi(VDirectory) + ']失败,原因是' + e.Message);
- Exit;
- end;
- end;
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'创建目录[' + Utf8ToAnsi(VDirectory) + ']');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1GetFileSize
- 功能: 允许服务器检索在服务器文件系统的文件的大小
- 参数: ASender: TIdFTPServerThread; const AFilename: string; var VFileSize: Int64
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1GetFileSize( ASender: TIdFTPServerThread;
- const AFilename: string; var VFileSize: Int64 ) ;
- begin
- VFileSize := FileSizeByName( TransLatePath( AFilename, ASender.HomeDir ) ) ;
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'获取文件大小');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1DeleteFile
- 功能: 允许从服务器中删除的文件系统中的文件
- 参数: ASender: TIdFTPServerThread; const APathname: string
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1DeleteFile( ASender: TIdFTPServerThread;
- const APathname: string ) ;
- begin
- try
- DeleteFile( pchar( TransLatePath( ASender.CurrentDir + '/' + APathname, ASender.HomeDir ) ) ) ;
- except
- on e:Exception do
- begin
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'删除文件[' + Utf8ToAnsi(APathname) + ']失败,原因是' + e.Message);
- Exit;
- end;
- end;
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'删除文件[' + Utf8ToAnsi(APathname) + ']');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1ChangeDirectory
- 功能: 允许服务器选择一个文件系统路径
- 参数: ASender: TIdFTPServerThread; var VDirectory: string
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1ChangeDirectory( ASender: TIdFTPServerThread;
- var VDirectory: string ) ;
- begin
- VDirectory := GetNewDirectory( ASender.CurrentDir, VDirectory ) ;
- if Assigned(FOnFtpNotifyEvent) then
- OnFtpNotifyEvent(Now, ASender.Connection.Socket.Binding.PeerIP,'进入目录[' + Utf8ToAnsi(VDirectory) + ']');
- end;
- {-------------------------------------------------------------------------------
- 过程名: TFTPServer.IdFTPServer1DisConnect
- 功能: 失去网络连接
- 参数: AThread: TIdPeerThread
- 返回值: 无
- -------------------------------------------------------------------------------}
- procedure TFTPServer.IdFTPServer1DisConnect( AThread: TIdPeerThread ) ;
- begin
- // nothing much here
- end;
- end.
使用工程示例:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, FTPServer;
type
TForm1 = class(TForm)
btn1: TButton;
btn2: TButton;
edt_BorrowDirectory: TEdit;
lbl1: TLabel;
mmo1: TMemo;
lbl2: TLabel;
edt_BorrowPort: TEdit;
lbl3: TLabel;
edt_UserName: TEdit;
lbl4: TLabel;
edt_UserPassword: TEdit;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
procedure TFTPServer1FtpNotifyEvent(ADatetime: TDateTime;AUserIP, AEventMessage: string);
private
FFtpServer: TFTPServer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
begin
if not Assigned(FFtpServer) then
begin
FFtpServer := TFTPServer.Create;
FFtpServer.UserName := Trim(edt_UserName.Text);
FFtpServer.UserPassword := Trim(edt_UserPassword.Text);
FFtpServer.BorrowDirectory := Trim(edt_BorrowDirectory.Text);
FFtpServer.BorrowPort := StrToInt(Trim(edt_BorrowPort.Text));
FFtpServer.OnFtpNotifyEvent := TFTPServer1FtpNotifyEvent;
FFtpServer.Run;
mmo1.Lines.Add(DateTimeToStr(Now) + #32 +'FTP服务器已开启,本机IP地址:' + FFtpServer.GetBindingIP);
end;
end;
procedure TForm1.btn2Click(Sender: TObject);
begin
if Assigned(FFtpServer) then
begin
FFtpServer.Stop;
FreeAndNil(FFtpServer);
mmo1.Lines.Add(DateTimeToStr(Now) + #32 +'FTP服务器已关闭');
end;
end;
procedure TForm1.TFTPServer1FtpNotifyEvent(ADatetime: TDateTime;AUserIP, AEventMessage: string);
begin
mmo1.Lines.Add(DateTimeToStr(ADatetime) + #32 + AUserIP + #32 + AEventMessage);
SendMessage(mmo1.Handle,WM_VSCROLL,SB_PAGEDOWN,0);
end;
end.
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, FTPServer;
type
TForm1 = class(TForm)
btn1: TButton;
btn2: TButton;
edt_BorrowDirectory: TEdit;
lbl1: TLabel;
mmo1: TMemo;
lbl2: TLabel;
edt_BorrowPort: TEdit;
lbl3: TLabel;
edt_UserName: TEdit;
lbl4: TLabel;
edt_UserPassword: TEdit;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
procedure TFTPServer1FtpNotifyEvent(ADatetime: TDateTime;AUserIP, AEventMessage: string);
private
FFtpServer: TFTPServer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
begin
if not Assigned(FFtpServer) then
begin
FFtpServer := TFTPServer.Create;
FFtpServer.UserName := Trim(edt_UserName.Text);
FFtpServer.UserPassword := Trim(edt_UserPassword.Text);
FFtpServer.BorrowDirectory := Trim(edt_BorrowDirectory.Text);
FFtpServer.BorrowPort := StrToInt(Trim(edt_BorrowPort.Text));
FFtpServer.OnFtpNotifyEvent := TFTPServer1FtpNotifyEvent;
FFtpServer.Run;
mmo1.Lines.Add(DateTimeToStr(Now) + #32 +'FTP服务器已开启,本机IP地址:' + FFtpServer.GetBindingIP);
end;
end;
procedure TForm1.btn2Click(Sender: TObject);
begin
if Assigned(FFtpServer) then
begin
FFtpServer.Stop;
FreeAndNil(FFtpServer);
mmo1.Lines.Add(DateTimeToStr(Now) + #32 +'FTP服务器已关闭');
end;
end;
procedure TForm1.TFTPServer1FtpNotifyEvent(ADatetime: TDateTime;AUserIP, AEventMessage: string);
begin
mmo1.Lines.Add(DateTimeToStr(ADatetime) + #32 + AUserIP + #32 + AEventMessage);
SendMessage(mmo1.Handle,WM_VSCROLL,SB_PAGEDOWN,0);
end;
end.
结果如下图所示:
示例工程源码下载:http://download.csdn.net/source/3236325
http://blog.csdn.net/akof1314/article/details/6371984#comments