当然有了。TNMFTP Edit1: FTP host
Edit2: FTP User ID
Edit3: FTP Password (set the PasswordChar property to *)
Button1: Connect/Disconnect
Button2: List
Button3: Change Directory
Button4: Make Directory
Button5: Remove Directory
Button6: Delete File
Button7: Rename File
Button8: Reinitialize
Button9: Authenticate
Button10: Get Current Directory
Memo1: Status Display
StringGrid1: Directory Listing DisplayStatusBar1: Transfer progress ** Set the SimplePanel property of StatusBar1 to TRUE in the Object Inspector
* Set the ParseList property of NMFTP1 to TRUE in the Object InspectorInsert the following code into Button1's OnClick event:procedure TForm1.Button1Click(Sender: TObject);
begin
  if NMFTP1.Connected then
    NMFTP1.Disconnect
  else
    begin
      NMFTP1.Vendor := NMOS_AUTO;
      NMFTP1.Host := Edit1.Text;
      NMFTP1.UserID := Edit2.Text;
      NMFTP1.Password := Edit3.Text;
      NMFTP1.Connect;
    end;
end;When Button1 is clicked, if there is already a connection present, the Disconnect method is used to close the connection. If there is no connection present, the Vendor property is set to NMOS_AUTO, which will auto-detect the FTP host vendor, if possible. The Host property is set to the host name or IP address entered in Edit1. The UserID property is set to the username that has been entered in Edit2. The Password property is set to the value of Edit3, and a connection is established with the Connect method.Insert the following code into Button2's OnClick event:procedure TForm1.Button2Click(Sender: TObject);
begin
  NMFTP1.List;
end;When Button2 is clicked, the List method is executed to get a listing of files and directories in the current directory. Since the ParseList property was previously set to TRUE, the directory listing will be parsed and it's fields placed in the FTPDirectoryList property. 
Insert the following code into Button3's OnClick event:procedure TForm1.Button3Click(Sender: TObject);
var
  TheDir: String;
begin
  if InputQuery('Change Directory', 'Which directory?', TheDir) then
    NMFTP1.ChangeDir(TheDir);
end;When Button3 is clicked, the InputQuery function is used to obtain the name of a directory. If the Ok button is clicked, the ChangeDir method attempts to change the current directory to the directory specified.
Insert the following code into Button4's OnClick event:procedure TForm1.Button4Click(Sender: TObject);
var
  TheDir: String;
begin
  if InputQuery('Create Directory', 'Directory name?', TheDir) then
    NMFTP1.MakeDirectory(TheDir);
end;When Button4 is clicked, the InputQuery function is used to obtain the name of a directory. If the Ok button is clicked, the MakeDirectory method attempts to create the directory specified.
Insert the following code into Button5's OnClick event:procedure TForm1.Button5Click(Sender: TObject);
var
  TheDir: String;
begin
  if InputQuery('Remove Directory', 'Directory name?', TheDir) then    NMFTP1.RemoveDir(TheDir);
end;When Button5 is clicked, the InputQuery function is used to obtain the name of a directory. If the Ok button is clicked, the RemoveDir method attempts to remove the specified directory from the remote host.
Insert the following code into Button6's OnClick event:procedure TForm1.Button6Click(Sender: TObject);
var
  TheFile: String;
begin
  if InputQuery('Delete File', 'File name?', TheFile) then
    NMFTP1.Delete(TheFile);
end;When Button6 is clicked, the InputQuery function is used to obtain the name of a file. If the Ok button is clicked, the Delete method attempts to delete the file specified.Insert the following code into Button7's OnClick event:procedure TForm1.Button7Click(Sender: TObject);
var
  OldFile,
  NewFile: String;
begin
  if InputQuery('Rename file', 'File to rename?', OldFile) then
    if InputQuery('Rename file', 'New file name?', NewFile) then
      NMFTP1.Rename(OldFile, NewFile);
end;When Button7 is clicked, the InputQuery function is called twice. The first time, the user is prompted for the file to rename. If the user enters a filename and clicks the Ok button, the second InputQuery asks for the new name for the file. If the OK button is also clicked here, the Rename method attempts to rename the file specified.Insert the following code into Button8's OnClick event:procedure TForm1.Button8Click(Sender: TObject);
begin
  ShowMessage('After reinitilizing, you must click the authenticate button');
  NMFTP1.Reinitialize;
end;When Button8 is clicked, the ShowMessage procedure is used to display a warning that once the Reinitialize method is called, authentication is required. When the Ok button is clicked on the message, the Reinitialize method attempts to reinitialize the connection with the server back to the authentication state.
Insert the following code into Button9's OnClick event:procedure TForm1.Button9Click(Sender: TObject);
var  AnID,
  APass: String;
begin
  if InputQuery('Authentication needed', 'Enter User ID', AnID) then
    if InputQuery('Authentication needed', 'Enter Password', APass) then
      begin
        NMFTP1.DoCommand('USER '+AnID);
        NMFTP1.DoCommand('PASS '+APass);
      end;
end;When Button9 is clicked the InputQuery function is used to obtain the user's User ID. If the Ok button is clicked, InputQuery is called again to obtain the user's password. If the Ok button is clicked a second time, the DoCommand method is used to send the USER and PASS commands to the remote host, effectively logging in to the FTP host. ***Please note that this is the only way to continue an FTP session once the Reinitialize method has been called.
Insert the following code into Button10's OnClick event:procedure TForm1.Button10Click(Sender: TObject);
begin
  ShowMessage(NMFTP1.CurrentDir);
end;When Button10 is clicked, the ShowMessage procedure is used to display the value of the CurrentDir property, which contains the current working directory on the remote host.
Insert the following code into NMFTP1's OnAuthenticationFailed event:procedure TForm1.NMFTP1AuthenticationFailed(var Handled: Boolean);
var
  ThePass,
  TheID: String;
begin
  if MessageDlg('Authentication Failed. Retry?', mtConfirmation, [mbYes, mbNo], 0) = mrYes 
then
    begin
      ThePass := NMFTP1.Password;
      TheID := NMFTP1.UserID;
      InputQuery('Reauthenticate', 'Enter User ID', TheID);
      InputQuery('Reauthenticate', 'Enter Password', ThePass);
      NMFTP1.Password := ThePass;
      NMFTP1.UserID := TheID;      Handled := TRUE;
    end;
end;When authentication fails on the remote host (Password and UserID don't match, aren't correct), the OnAuthenticationFailed event is called. In this instance, a dialog box is displayed using the MessageDlg function. If the user clicks the Yes button to attempt authentication again, the InputQuery function is used to obtain a new UserID and Password. The Password and UserID properties are set to the new values accordingly, and the Handled parameter of the event is set to TRUE to allow the component to reauthenticate.Insert the following code into NMFTP1's OnAuthenticationNeeded event:procedure TForm1.NMFTP1AuthenticationNeeded(var Handled: Boolean);
var
  APass,
  AnID: String;
begin
  if NMFTP1.Password = '' then
    begin
      if InputQuery('Password needed', 'Enter password: ', APass) then
        begin
          NMFTP1.Password := APass;
          Handled := TRUE;
        end
      else
        Handled := FALSE;
    end;  if NMFTP1.UserID = '' then
    begin
      if InputQuery('User ID needed', 'Enter User ID: ', AnID) then
        begin
          NMFTP1.UserID := AnID;
          Handled := TRUE;
        end
      else
        Handled := FALSE;
    end;
end;If either the UserID or Password property are blank, the OnAuthenticationNeeded event is called. In this instance, if the Password property is blank, the InputQuery function is used to get a password. If the Ok button is clicked, the Password property is set to the new password, and the Handled parameter is set to FALSE. If the UserID property is blank, the InputQuery function is used to get a UserID. If the Ok button is clicked, the UserID property is set to the new value, and the Handled parameter is set to TRUE. If a password and/or user ID are not supplied, Handled is set to FALSE, which will cause an exception to be raised, and the connection to be cancelled.Insert the following code into NMFTP1's OnConnect event:procedure TForm1.NMFTP1Connect(Sender: TObject);
begin
  Memo1.Lines.Add('Connected');
  Button1.Caption := 'Disconnect';
end;The OnConnect event is called once a connection has been established with the remote FTP host. In this case, Memo1 is updated to display the connection notice, and the caption of Button1 is set to Disconnect, since Button1 is used for connecting and disconnecting.
Insert the following code into NMFTP1's OnDisconnect event:procedure TForm1.NMFTP1Disconnect(Sender: TObject);
begin
  Memo1.Lines.Add('Disconnected');
  Button1.Caption := 'Connect';
end;When the OnDisconnect event is called when the connection to the remote FTP host has been terminated, the disconnection notice is added to Memo1 (status display memo), and Button1's caption is set to Connect, since Button1 is used both for connecting and disconnecting.Insert the following code into NMFTP1's OnFailure event:procedure TForm1.NMFTP1Failure(var Handled: Boolean; Trans_Type: TCmdType);
begin
  case Trans_Type of
    cmdChangeDir: Memo1.Lines.Add('ChangeDir failed');
    cmdMakeDir: Memo1.Lines.Add('MakeDir failed');
    cmdDelete: Memo1.Lines.Add('Delete failed');
    cmdRemoveDir: Memo1.Lines.Add('RemoveDir failed');
    cmdList: Memo1.Lines.Add('List failed');
    cmdRename: Memo1.Lines.Add('Rename failed');
    cmdUpRestore: Memo1.Lines.Add('UploadRestore failed');
    cmdDownRestore: Memo1.Lines.Add('DownloadRestore failed');
    cmdDownload: Memo1.Lines.Add('Download failed');    cmdUpload: Memo1.Lines.Add('Upload failed');
    cmdAppend: Memo1.Lines.Add('UploadAppend failed');
    cmdReInit: Memo1.Lines.Add('Reinitialize failed');
    cmdAllocate: Memo1.Lines.Add('Allocate failed');
    cmdNList: Memo1.Lines.Add('NList failed');
    cmdDoCommand: Memo1.Lines.Add('DoCommand failed');
    cmdCurrentDir: Memo1.Lines.Add('CurrentDir failed');
  end;
end;The OnFailure event is called when a command has failed to execute properly. In this instance, the Trans_Type parameter is checked, and Memo1 is updated to display which command failed to execute.The Handled parameter is left to FALSE (the default), so an exception will be raised due to the failure.
Insert the following code into NMFTP1's OnPacketRecvd event:procedure TForm1.NMFTP1PacketRecvd(Sender: TObject);
begin
  StatusBar1.SimpleText := 'Received '+IntToStr(NMFTP1.BytesRecvd)+' bytes of '+IntToStr(NMFTP1.BytesTotal)+' total';
end;When data is received during a file transfer, the OnPacketRecvd event is called. This example updates the Statusbar StatusBar1 to display how many bytes of the total transfer have been received.
Insert the following code into NMFTP1's OnPacketSent event:procedure TForm1.NMFTP1PacketSent(Sender: TObject);begin
  StatusBar1.SimpleText := 'Sent '+IntToStr(NMFTP1.BytesSent)+' bytes of '+IntToStr(NMFTP1.BytesTotal)+' total';
end;When data is sent to the remote host during a file transfer, the OnPacketSent event is called. This example updates the Statusbar StatusBar1 to display how many bytes of the total transfer have been sent.
Insert the following code into NMFTP1's OnTransactionStart event:procedure TForm1.NMFTP1TransactionStart(Sender: TObject);
begin
  Memo1.Lines.Add('Data transfer start');
end;When a data transaction takes place in the TNMFTP component, the OnTransactionStart event is called to signify the data transaction's beginning. This example updates Memo1 to display that the data transfer has started.Insert the following code into NMFTP1's OnTransactionStop event:procedure TForm1.NMFTP1TransactionStop(Sender: TObject);
begin
  Memo1.Lines.Add('Data transfer end');
end;When a data transaction completes in the TNMFTP component, the OnTransactionStop event is called to signify the data transaction's end. This example updates Memo1 to display that the data transfer has finished.
Insert the following code into NMFTP1's OnSuccess event:procedure TForm1.NMFTP1Success(Trans_Type: TCmdType);
var
  I: Integer;
begin
  case Trans_Type of
    cmdList:
      begin
        for I := 0 to (StringGrid1.ColCount - 1) do          StringGrid1.Cols[I].Clear;
        StringGrid1.RowCount := NMFTP1.FTPDirectoryList.name.Count;
        StringGrid1.ColCount := 4;
        StringGrid1.Cells[0, 0] := 'Filename';
        StringGrid1.Cells[1, 0] := 'File Size';
        StringGrid1.Cells[2, 0] := 'Modified Date';
        StringGrid1.Cells[3, 0] := 'Attributes';
        for I := 0 to (NMFTP1.FTPDirectoryList.name.Count - 1) do
          with NMFTP1.FTPDirectoryList do
            begin
              StringGrid1.Cells[0, I+1] := name[I];              StringGrid1.Cells[1, I+1] := Size[I];
              StringGrid1.Cells[2, I+1] := ModifDate[I];
              StringGrid1.Cells[3, I+1] := Attribute[I];
            end;
      end;
    cmdChangeDir:
      begin
        Memo1.Lines.Add('ChangeDir successful');
        NMFTP1.List;
      end;
    cmdMakeDir: Memo1.Lines.Add('MakeDir successful');
    cmdRemoveDir: Memo1.Lines.Add('RemoveDir successful');
    cmdDelete: Memo1.Lines.Add('Delete successful');
    cmdRename: Memo1.Lines.Add('Rename successful');    cmdReInit: Memo1.Lines.Add('Reinitialize successful');
    cmdCurrentDir: Memo1.Lines.Add('CurrentDir successful');
  end;
end;When an FTP command has completed successfully, the OnSuccess event is called. In this case, the Trans_Type parameter is tested, and Memo1 is updated to display the success of the command.
If the command was a call to the List method, StringGrid1 is used to display the resulting directory list upon successful completion by using the FTPDirectoryList property to separate the different fields of the directory listing. If the command was a call to the ChangeDir method, the new directory listing is automatically initiated by the List method.Insert the following code into NMFTP1's OnUnSupportedFunction event:procedure TForm1.NMFTP1UnSupportedFunction(Trans_Type: TCmdType);
begin
  case Trans_Type of
    cmdChangeDir: Memo1.Lines.Add('ChangeDir not supported by this server');
    cmdMakeDir: Memo1.Lines.Add('MakeDir not supported by this server');
    cmdDelete: Memo1.Lines.Add('Delete not supported by this server');
    cmdRemoveDir: Memo1.Lines.Add('RemoveDir not supported by this server');
    cmdList: Memo1.Lines.Add('List not supported by this server');
    cmdRename: Memo1.Lines.Add('Rename not supported by this server');
    cmdUpRestore: Memo1.Lines.Add('UploadRestore not supported by this server');    cmdDownRestore: Memo1.Lines.Add('DownloadRestore not supported by this server');
    cmdDownload: Memo1.Lines.Add('Download not supported by this server');
    cmdUpload: Memo1.Lines.Add('Upload not supported by this server');
    cmdAppend: Memo1.Lines.Add('UploadAppend not supported by this server');
    cmdReInit: Memo1.Lines.Add('Reinitialize not supported by this server');
    cmdAllocate: Memo1.Lines.Add('Allocate not supported by this server');
    cmdNList: Memo1.Lines.Add('NList not supported by this server');    cmdDoCommand: Memo1.Lines.Add('DoCommand not supported by this server');
    cmdCurrentDir: Memo1.Lines.Add('CurrentDir not supported by this server');
  end;
end;