Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IDFTP DirExists and MakeDir

I am using Indy IDFTP to make a directory. I need to find a reliable way to determine if a directory exists and if it does not exist, to call MakeDir. I have tried the following code but an exception did not occur when List was called so MakeDir was not executed even though the directory did not exist at the time. How can I determine if a directory exists and create the directory if it does not exist?

{ Check to see if the '/public_html/XXX/' + iDomain + 'Thumbnails' directory exists }
    try
      IdFTP1.List(nil, '/public_html/XXX/' + iDomain + 'Thumbnails', False);
    except
      on e: EIdReplyRFCError do
      begin
        { '/public_html/XXX/' + iDomain + 'Thumbnails' directory does not exist }
        StatusBar1.SimpleText := 'Making thumbnail directory...';
        StatusBar1.Update;
        iFolder := '/public_html/XXX/' + iDomain;
        { Change directory to /public_html/XXX/iDomain }
        IdFTP1.ChangeDir(iFolder);
        iFolder := 'Thumbnails';
        { Create FTP Directory for Thumbnails }
        IdFTP1.MakeDir(iFolder);
      end;
    end;

During my testing the directory did not exist but at runtime e was nil? Is my approach to this correct?

like image 333
Bill Avatar asked Jan 15 '15 00:01

Bill


2 Answers

If TIdFTP.List() is not raising an exception, the FTP server is most likely returning a 450 reply code, which simply means "Requested file action not taken". TIdFTP.InternalGet() (which is used by TIdFTP.List(), TIdFTP.ExtListDir(), and TIdFTP.Get()) does not treat 450 as an error condition, as some servers (like Ericsson Switch FTP) send 450 when listing the contents of an empty but otherwise existent directory, so there is no listing data to send. Some servers do send 450 when the requested directory does not exist, though. TIdFTP.List() does not try to differentiate. However, if TIdFTP.List() does not raise an exception, you can look at the TIdFTP.LastCmdResult property to differentiate manually if needed.

Also, you can't just rely on the fact that an exception is raised to mean the folder does not exist. Any number of possible errors could occur. You have to actually look at the error and act accordingly, eg:

var
  Exists: Boolean;

try
  IdFTP1.List(nil, '/public_html/XXX/' + iDomain + 'Thumbnails', False);
  Exists := True;
  if IdFTP1.LastCmdResult.NumericCode = 450 then
  begin
    if (IdFTP1.LastCmdResult.Text.Text has a message like 'No such file or directory' or similar) then begin
      Exists := False;
    end;
    // look for other possible text messages...
  end;
except
  on e: EIdReplyRFCError do
  begin
    if (e.ErrorCode <> 550) or (e.Message does not have a message like 'Directory not found' or similar) then begin
      raise;
    end;
    Exists := false;
  end;
end;

if not Exists then
begin
  { '/public_html/XXX/' + iDomain + 'Thumbnails' directory does not exist }
  StatusBar1.SimpleText := 'Making thumbnail directory...';
  StatusBar1.Update;
  iFolder := '/public_html/XXX/' + iDomain;
  { Change directory to /public_html/XXX/iDomain }
  IdFTP1.ChangeDir(iFolder);
  iFolder := 'Thumbnails';
  { Create FTP Directory for Thumbnails }
  IdFTP1.MakeDir(iFolder);
end;

A better way would be to either:

  1. ChangeDir() to the target directory directly and see if it fails. If so, start walking backwards through the path, calling ChangeDir() for each parent directory until one finally succeeds, then walk back up the path using MakeDir() and ChangeDir() to create the missing sub-directories as needed.

  2. Start with the first directory in the path and ChangeDir() to it, then List() it to see if the next sub-folder is present, MakeDir() it if needed, then ChangeDir() to it, and repeat as needed until you reach the target directory.

Welcome to FTP. It is not a very efficient protocol for directory management.

like image 88
Remy Lebeau Avatar answered Nov 13 '22 09:11

Remy Lebeau


Simple solution is

      IdFTP.ChangeDir('/www/image/catalog/');  // connect to to directory where you want to add folder

      try
        IdFTP.MakeDir(new_Dir_name);          // try to create folder
        IdFTP.ChangeDir('/www/image/catalog/' + new_Dir_name );  // connect to new folder
      except
        IdFTP.ChangeDir('/www/image/catalog/' + new_Dir_name ); // if folder exist just connect to folder which exist
      end;
like image 40
Mepcuk Avatar answered Nov 13 '22 10:11

Mepcuk