多个客户端程序可以同时发送文件到服务器端,服务端程序自动接收文件并保存到指定目录。

解决方案 »

  1.   

    可以,利用Indy组件包的IdTcpServer 和IdTcpClient 组件,因为该控件已经自动实现了多线程,所以可以满足你的要求。
      

  2.   

    客户端程序如下:
    unit U_FtpTool;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
      IdTCPClient, IdFTP, FileCtrl,IdFTPCommon, ExtCtrls, ComCtrls,IdFTPList,
      ImgList,IdGlobal,StrUtils, ShellCtrls, Buttons;type
      TMyFirstThread = class(TThread)
      private  protected
        procedure Execute;override;
      end;type
      TForm1 = class(TForm)
        IdFTP1: TIdFTP;
        ImageList1: TImageList;
        ImageList2: TImageList;
        Panel1: TPanel;
        Label1: TLabel;
        HostEdit: TEdit;
        Label2: TLabel;
        UserIDEdit: TEdit;
        Label3: TLabel;
        PasswordEdit: TEdit;
        Label4: TLabel;
        PortEdit: TEdit;
        Button1: TButton;
        Panel2: TPanel;
        ShellComboBox1: TShellComboBox;
        ShellListView1: TShellListView;
        Panel3: TPanel;
        ListView1: TListView;
        Panel4: TPanel;
        CurrentDirEdit: TEdit;
        SpeedButton1: TSpeedButton;
        Label5: TLabel;
        Button2: TButton;
        Splitter1: TSplitter;
        Splitter2: TSplitter;
        ListBox1: TListBox;
        Panel5: TPanel;
        ProgressBar1: TProgressBar;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure ListView1DblClick(Sender: TObject);
        procedure SpeedButton1Click(Sender: TObject);
        procedure IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode;
          const AWorkCount: Integer);
        procedure FormCreate(Sender: TObject);
        procedure IdFTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
          const AWorkCountMax: Integer);
        procedure IdFTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
        procedure PasswordEditKeyPress(Sender: TObject; var Key: Char);
      private
        ByteCount:Integer;
        YUpLoadByte:integer;
        Thread1:TMyFirstThread;
        UpLoadType:String;//'1'表示上传类型是文件夹,'0'表示上传类型是文件
        FileSize:Integer;
        procedure List(DirName:string);
        procedure UpLoad(Remote_path,Local_path:string);
        function GetDirectorySize(ADirectory: string): Integer;
        procedure AfterUpLoad(Send : TObject);
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementationuses U_ModalDialog;{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      if IdFTP1.Connected then
         IdFTP1.Disconnect;
      IdFTP1.Host:=Trim(HostEdit.Text);
      if Trim(UserIDEdit.Text)='' then
      begin
        IdFTP1.Username:='anonymous';
        IdFTP1.Password:='';
      end
      else
      begin
        IdFTP1.Username:=Trim(UserIDEdit.Text);
        IdFTP1.Password:=Trim(PasswordEdit.Text);
      end;
      IdFTP1.Port:=StrToInt(PortEdit.Text);
      try
        IdFTP1.Connect;
      except
        ShowMessage('连接失败');
      end;
      CurrentDirEdit.Text:='/';
      Self.List(CurrentDirEdit.Text);
      Button2.Enabled:=True;
      Panel3.Visible:=True;
    end;
    procedure TForm1.UpLoad(Remote_path,Local_path:string);
    var strl1,strl2,strl3:TStringList;
        sr: TSearchRec;
        i,j,DirCount,FileCount:integer;
        str:string;
    begin
      IdFTP1.ChangeDir(Remote_path);  DirCount:=0;FileCount:=0;  IdFTP1.MakeDir(Copy(Local_path,LastDelimiter('\',Local_path)+1,length(Local_path)));  if FindFirst(Local_path + '\*.*', faDirectory, sr) = 0 then
      begin
        strl1:=TStringList.Create;
        repeat
          if (sr.Attr = faDirectory) and(sr.Name<>'.') and (sr.Name<>'..') then
          begin
            strl1.Add(sr.Name);
            Inc(DirCount);
          end;
        until FindNext(sr) <> 0;
        FindClose(sr);
      end;  for i:=0 to DirCount-1 do
      begin
        UpLoad(Remote_path+'/'+Copy(Local_path,LastDelimiter('\',Local_path)+1,length(Local_path)),Local_path+'\'+strl1.Strings[i]);
      end;  if FindFirst(Local_path + '\*.*',faAnyFile, sr )=0 then
      begin
        strl2:=TStringList.Create;
        repeat
          if (sr.Attr <> faDirectory) then
          begin
            strl2.Add(sr.Name);
            Inc(FileCount);
          end;
        until FindNext(sr) <>0;
        FindClose(sr);
      end;  IdFTP1.ChangeDir(Remote_path+'/'+Copy(Local_path,LastDelimiter('\',Local_path)+1,length(Local_path)));  for j:=0 to FileCount-1 do
      begin
        try
          IdFTP1.Put(Local_path+'\'+strl2[j],IdFTP1.RetrieveCurrentDir+'/'+strl2[j]);
          ListBox1.Items.Add('@_@   '+strl2[j]+'上传成功!');
        except
          ListBox1.Items.Add(':o   '+strl2[j]+'上传失败!');
          Continue;
        end;
      end;
    end;
      

  3.   

    procedure TForm1.Button2Click(Sender: TObject);
    var strl1:TStringList;
        i:integer;
    begin
      if ShellListView1.SelectedFolder=nil then
      begin
        ShowMessage('请选择要上传的文件或文件夹');
        Exit;
      end;  strl1:=TStringList.Create;  for i:=0 to IdFTP1.DirectoryListing.Count-1 do
      begin
        strl1.Add(IdFTP1.DirectoryListing.Items[i].FileName);
      end;  for i:=0 to strl1.Count-1 do
      begin
        if strl1[i] <> ShellListView1.SelectedFolder.DisplayName then
           Continue
        else
        begin
         if Application.MessageBox('目录或文件已经存在,是否替换?','提示',MB_OkCancel+MB_IconQuestion)=IdOk then
         begin
           IdFTP1.Delete(strl1[i]);
         end
         else
         begin
           Exit;
         end;
    //      ShowMessage('目录或文件已经存在');
    //      Exit;
        end;
      end;
      Button2.Enabled:=False;
      ListBox1.Clear;
      if ShellListView1.SelectedFolder.IsFolder then
      begin
        UpLoadType:='1';
        YUpLoadByte:=0;
        ProgressBar1.Position:=0;
        ByteCount:=GetDirectorySize(ShellListView1.SelectedFolder.PathName);
        ProgressBar1.Min:=0;
        ProgressBar1.Max:=ByteCount;
      end;  if not ShellListView1.SelectedFolder.IsFolder then
      begin
         UpLoadType:='0';
         YUpLoadByte:=0;
         ProgressBar1.Position:=0;
         ByteCount:=FileSizeByName(ShellListView1.SelectedFolder.PathName);
         ProgressBar1.Max:=ByteCount;
      end;
      if not Assigned(Form2) then
         Form2:=TForm2.Create(Application);
      Form2.Show;
      Form1.ListView1.Enabled:=False;
      Form1.Button1.Enabled:=False;
      Thread1:=TMyFirstThread.Create(False);
      Thread1.Priority:=tpNormal;
      Thread1.OnTerminate:=AfterUpLoad;
      Thread1.FreeOnTerminate:=True;
    end;procedure TForm1.List(DirName: string);
    var NewItem:TListItem;
        i:integer;
        LS: TStringList;
    begin
      Ls:=TStringList.Create;  ListView1.Clear;
      IdFTP1.ChangeDir(DirName);
      IdFTP1.List(Ls);
      CurrentDirEdit.Text:=IdFTP1.RetrieveCurrentDir;
      for i:=0 to IdFTP1.DirectoryListing.Count-1 do
      begin
        With IdFTP1.DirectoryListing.Items[i] do
        begin
          if (FileName='.') OR (FileName='..')  then Continue;
          NewItem:=ListView1.Items.Add;
          NewItem.Caption:=FileName;
          NewItem.SubItems.Add(IntToStr(Size));
          if ItemType = ditDirectory then
          begin
             NewItem.StateIndex:=0;
             NewItem.SubItems.Add('文件文件夹');
          end
          else
          begin
            NewItem.SubItems.Add('其它类型');
          end;
          NewItem.SubItems.Add(FormatDateTime('yyyy/mm/dd hh:mm', ModifiedDate));
          NewItem.SubItems.Add(OwnerName);
        end;
      end;
    end;procedure TForm1.ListView1DblClick(Sender: TObject);
    begin
      if ListView1.Selected=nil then Exit;
      if  IdFTP1.DirectoryListing.Items[ListView1.ItemIndex].ItemType = ditDirectory then
          Self.List(ListView1.Items[ListView1.ItemIndex].Caption);
    end;
    procedure TForm1.SpeedButton1Click(Sender: TObject);
    begin
      if IdFTP1.RetrieveCurrentDir<>'/' then
         Self.List('..');
    end;procedure TForm1.IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCount: Integer);
    begin
      ProgressBar1.Position:=AWorkCount+YUpLoadByte;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      ByteCount:=0;
      YUpLoadByte:=0;
    end;function TForm1.GetDirectorySize(ADirectory: string): Integer;
    var
      Dir: TSearchRec;
      Ret: integer;
      Path: string;
    begin
      Result := 0;
      Path := ExtractFilePath(ADirectory);
      Ret := Sysutils.FindFirst(ADirectory, faAnyFile, Dir);
      if Ret <> NO_ERROR then exit;
      try
        while ret = NO_ERROR do
        begin
          inc(Result, Dir.Size);
          if (Dir.Attr in [faDirectory]) and (Dir.Name[1] <> '.') then
            Inc(Result, GetDirectorySize(Path + Dir.Name + '\*.*'));
          Ret := Sysutils.FindNext(Dir);
        end;
      finally
        Sysutils.FindClose(Dir);
      end;
    end;{ TMyFirstThread }procedure TForm1.AfterUpLoad(Send : TObject);
    begin
      Form1.ListBox1.Items.Add('全部上传完成');
      Form1.List(Form1.CurrentDirEdit.Text);
      Form1.Button2.Enabled:=True;
      Form1.Button1.Enabled:=True;
      Form1.ListView1.Enabled:=True;
      Form2.Close;
    end;procedure TMyFirstThread.Execute;
    begin
      inherited;
      if Form1.UpLoadType='1' then
         Form1.UpLoad(Form1.IdFTP1.RetrieveCurrentDir,Form1.ShellListView1.SelectedFolder.PathName);
      if Form1.UpLoadType='0' then
      begin
        try
          Form1.IdFTP1.Put(Form1.ShellListView1.SelectedFolder.PathName,Form1.IdFTP1.RetrieveCurrentDir+'/'+Form1.ShellListView1.SelectedFolder.DisplayName);
          Form1.ListBox1.Items.Add('@_@   '+Form1.ShellListView1.SelectedFolder.DisplayName+'上传成功!');
        except
          Form1.ListBox1.Items.Add(':o   '+Form1.ShellListView1.SelectedFolder.DisplayName+'上传失败!');
        end;
      end;
    end;procedure TForm1.IdFTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCountMax: Integer);
    begin
      FileSize:=AWorkCountMax;
    end;procedure TForm1.IdFTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
    begin
      YUpLoadByte:=YUpLoadByte+FileSize;
    end;procedure TForm1.PasswordEditKeyPress(Sender: TObject; var Key: Char);
    begin
      if Key=#13 then
         Button1.Click;
    end;end.
      

  4.   

    服务器端程序如下:
    program FTPServer_console;
    (*
    Sample of the usage of the TIdFtpServer component.
    Also shows how to use Indy in console apps
    Created by: Bas Gooijen ([email protected])Disclaimer:
      Use it at your own risk, it could contain bugs.Copyright:
      Freeware for all use
    *){$APPTYPE console}
    uses
      Classes,
      windows,
      sysutils,
      IdFTPList,
      IdFTPServer,
      idtcpserver,
      IdSocketHandle,
      idglobal,
      IdHashCRC;type
      TFTPServer = class
      private
        { Private declarations }
        IdFTPServer: tIdFTPServer;
        procedure IdFTPServer1UserLogin( ASender: TIdFTPServerThread; const AUsername, APassword: string; var AAuthenticated: Boolean ) ;
        procedure IdFTPServer1ListDirectory( ASender: TIdFTPServerThread; const APath: string; ADirectoryListing: TIdFTPListItems ) ;
        procedure IdFTPServer1RetrieveFile( ASender: TIdFTPServerThread; const AFilename: string; var VStream: TStream ) ;
        procedure IdFTPServer1StoreFile( ASender: TIdFTPServerThread; const AFilename: string; AAppend: Boolean; var VStream: TStream ) ;
        procedure IdFTPServer1MakeDirectory( ASender: TIdFTPServerThread; var VDirectory: string ) ;
    //    procedure IdFTPServer1GetFileSize( ASender: TIdFTPServerThread; const AFilename: string; var VFileSize: Int64 ) ;
        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;
      end;
      

  5.   

    socket也可以,服务端下传的例子:
    服务端:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ScktComp;type
      TForm1 = class(TForm)
        ServerSocket1: TServerSocket;
        Memo1: TMemo;
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure ServerSocket1ClientConnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure Button2Click(Sender: TObject);
      private
        function SenfFile: boolean;
        { Private declarations }
      public
        { Public declarations }
      end;
    Const
      BufSize=4096;var
      Form1: TForm1;
      I:integer;
      StarSize: Longint;
      Stream:TMemoryStream;
    implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      Memo1.Lines.Clear;
      ServerSocket1.Active:=False;
      ServerSocket1.Active:=True;
      Memo1.Lines.Add('服务: '+ServerSocket1.Socket.LocalHost+' 已开启');
    end;procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      Memo1.Lines.Add('Client:'+Socket.RemoteHost +'已连接');
    end;procedure TForm1.Button2Click(Sender: TObject);
    var
      S:string;
    begin
      Stream:=nil;
      Stream:=TMemoryStream.Create;
      Stream.LoadFromFile('C:\1.rar');
      Stream.Position:=0;
      StarSize := Stream.Size;
      if  SenfFile then S:='发送成功'  else S:='发送失败';
      Memo1.Lines.Add(s);
    end;function TForm1.SenfFile:boolean;
    var
      sendsize: integer;
      Buf: array[0..BufSize - 1] of char;
    begin
      while StarSize>0 do
      begin
        if StarSize >= BufSize then
           sendsize := BufSize
        else
           sendsize := StarSize;
        Stream.Read(Buf, sendsize);
        StarSize := StarSize - sendsize;
        Sleep(200);
        ServerSocket1.Socket.Connections[0].SendBuf(Buf, sendsize);
        Memo1.Lines.Add(IntToStr(sendsize));
      end;                                             
      Result:=True;
    end;end.客户端:unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ScktComp, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        ClientSocket1: TClientSocket;
        Edit1: TEdit;
        Button2: TButton;
        Button3: TButton;
        Button4: TButton;
        procedure Button1Click(Sender: TObject);
        procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
        procedure Button2Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
      private
        function SenfFile: boolean;
        { Private declarations }
      public
        { Public declarations }
      end;
    Const
      BufSize=8192;
      SendLth=4096;
    var
      Form1: TForm1;
      I:integer;
      Stream:TMemoryStream;
      StarSize:integer;
    implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      ClientSocket1.Active:=False;
      Memo1.Lines.Clear;
      ClientSocket1.Host:=Edit1.Text;
      ClientSocket1.Port:=5158;
      ClientSocket1.Active:=True;
      Memo1.Lines.Add('已经连接到:'+Edit1.Text);
      Stream:=nil;
      Stream:=TMemoryStream.Create;
    end;procedure TForm1.ClientSocket1Read(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      sendsize: Longint;
      buf:array[0..bufsize] of char;
      s:string;
    begin
      sendsize:=Socket.ReceiveBuf(Buf,Socket.ReceiveLength);
      if sendsize>0 then
      begin
        Stream.Write(buf,sendsize);
      end;
        Memo1.Lines.Add(IntToStr(sendsize));
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
        Stream.SaveToFile('C:\222.rar');
        Memo1.Lines.Add(IntToStr(Stream.Size));
    end;function TForm1.SenfFile:boolean;
    begin
    end;
    procedure TForm1.Button4Click(Sender: TObject);
    begin
      ClientSocket1.Active:=true;
      ClientSocket1.Socket.SendText('asdfdsfsdf');
    end;end.
      

  6.   

    服务器端程序继续:
    constructor TFTPServer.Create;
    begin
      IdFTPServer := tIdFTPServer.create( nil ) ;
      IdFTPServer.DefaultPort := 21;
      IdFTPServer.AllowAnonymousLogin := False;
      IdFTPServer.EmulateSystem := ftpsUNIX;
      IdFTPServer.HelpReply.text := '帮助还没实现';
      IdFTPServer.OnChangeDirectory := IdFTPServer1ChangeDirectory;
      IdFTPServer.OnChangeDirectory := IdFTPServer1ChangeDirectory;
    //  IdFTPServer.OnGetFileSize := IdFTPServer1GetFileSize;
      IdFTPServer.OnListDirectory := IdFTPServer1ListDirectory;
      IdFTPServer.OnUserLogin := IdFTPServer1UserLogin;
      IdFTPServer.OnRetrieveFile := IdFTPServer1RetrieveFile;
      IdFTPServer.OnStoreFile := IdFTPServer1StoreFile;
      IdFTPServer.OnMakeDirectory := IdFTPServer1MakeDirectory;
      IdFTPServer.Greeting.Text.Text := '欢迎进入FTP服务器! ';
      IdFTPServer.Greeting.NumericCode := 220;
    //  IdFTPServer.OnDisconnect := IdFTPServer1DisConnect;
    //  with IdFTPServer.CommandHandlers.add do
    //  begin
    //    Command := 'XCRC';
    //    OnCommand := IdFTPServer1CommandXCRC;
    //  end;
      IdFTPServer.Active := true;
    end;
    {
    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;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;
    }
    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;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;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;function TFTPServer.TransLatePath( const APathname, homeDir: string ) : string;
    var
      tmppath: string;
    begin
      result := SlashToBackSlash( homeDir ) ;
      tmppath := SlashToBackSlash( 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;{function GetSizeOfFile( const APathname: string ) : int64;
    begin
      result := FileSizeByName( APathname ) ;
    end;
    }
    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;procedure TFTPServer.IdFTPServer1UserLogin( ASender: TIdFTPServerThread;
      const AUsername, APassword: string; var AAuthenticated: Boolean ) ;
    begin
      AAuthenticated := ( AUsername = 'wjh' ) and ( APassword = 'jhw' ) ;
      if not AAuthenticated then
        exit;
      ASender.HomeDir := './';
      asender.currentdir := '/';
    end;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 := Filename;
        listitem.OwnerName := 'anonymous';
        listitem.GroupName := 'all';
        listitem.OwnerPermissions := 'rwx';
        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;procedure TFTPServer.IdFTPServer1RetrieveFile( ASender: TIdFTPServerThread;
      const AFilename: string; var VStream: TStream ) ;
    begin
      VStream := TFileStream.create( translatepath( AFilename, ASender.HomeDir ) , fmopenread or fmShareDenyWrite ) ;
    end;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 ) ;
    end;procedure TFTPServer.IdFTPServer1MakeDirectory( ASender: TIdFTPServerThread;
      var VDirectory: string ) ;
    begin
      MkDir( TransLatePath( VDirectory, ASender.HomeDir ) ) ;
    end;{procedure TFTPServer.IdFTPServer1GetFileSize( ASender: TIdFTPServerThread;
      const AFilename: string; var VFileSize: Int64 ) ;
    begin
    //  VFileSize := GetSizeOfFile( TransLatePath( AFilename, ASender.HomeDir ) ) ;
    end; }procedure TFTPServer.IdFTPServer1ChangeDirectory( ASender: TIdFTPServerThread;
      var VDirectory: string ) ;
    begin
      VDirectory := GetNewDirectory( ASender.CurrentDir, VDirectory ) ;
    end;{procedure TFTPServer.IdFTPServer1DisConnect( AThread: TIdPeerThread ) ;
    begin
      //  nothing much here
    end;}begin
      with TFTPServer.Create do
      try
        writeln( '程序正在运行, 按 [enter]键退出。' ) ;
        readln
      finally
        free;
      end;
    end.
      

  7.   

    可不可以换个方式考虑,直接FTP发送岂不是更好?