IDFTP DirExists和MakeDir

时间:2015-01-15 00:50:01

标签: delphi indy10 delphi-xe7

我使用Indy IDFTP制作目录。我需要找到一种可靠的方法来确定目录是否存在以及它是否存在,以便调用MakeDir。我尝试了以下代码,但是在调用List时没有发生异常,因此即使当时目录不存在,MakeDir也没有执行。如何确定目录是否存在并创建目录(如果该目录不存在)?

{ 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;

在我测试期间,目录不存在,但在运行时e是零?我的方法是否正确?

3 个答案:

答案 0 :(得分:7)

如果TIdFTP.List()没有引发异常,则FTP服务器很可能会返回450回复代码,这意味着"未采取请求的文件操作"。 TIdFTP.InternalGet()(由TIdFTP.List()TIdFTP.ExtListDir()TIdFTP.Get()使用)不会将450视为错误情况,因为某些服务器(如Ericsson Switch FTP) )列出空的但存在的目录的内容时发送450,因此没有要发送的列表数据。但是,当请求的目录不存在时,某些服务器会发送450TIdFTP.List()不会尝试区分。但是,如果TIdFTP.List()未引发异常,您可以查看TIdFTP.LastCmdResult属性,以便在需要时手动区分。

此外,您不能仅仅依赖于引发异常以表示该文件夹不存在的事实。可能发生任何数量的可能错误。您必须实际查看错误并采取相应措施,例如:

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;

更好的方法是:

  1. ChangeDir()直接到目标目录并查看它是否失败。如果是这样,开始向后走过路径,为每个父目录调用ChangeDir(),直到最终成功,然后使用MakeDir()ChangeDir()向上走回路径以创建缺少的子目录根据需要。

  2. 从路径中的第一个目录开始,然后ChangeDir()开始,然后List()查看下一个子文件夹是否存在,MakeDir()如果需要,然后ChangeDir()到它,并根据需要重复,直到到达目标目录。

  3. 欢迎使用FTP。它不是一个非常有效的目录管理协议。

答案 1 :(得分:0)

以下是上传文件夹的方法。 Source

{
  Upload the LocalDir to an FTP server, in the RemoteDir.
  If RemoteDir does not exist it is created.
  All files and subfolders of LocalDir will be uploaded.
  FTP parameters (username, password, server) must be already provided.
  The caller must connnect to the server before calling UploadFolderToFtp and disconnect after that }
procedure UploadFolderToFtp(FTP: TIdFTP; LocalDir, RemoteDir, Filter: string);


   procedure GoToSubDir(SubDir: string);
   VAR
     details, nodetails: TStringList;
     k: Integer;
   begin
    details   := TStringList.Create;       //get folder contents from ftp. one with details, one without
    nodetails := TStringList.Create;
    TRY
     FTP.List(details, '', True);
     FTP.List(nodetails, '', False);

     //we only want to have directories in the list (without '.' and '..')
     for k := details.Count - 1 downto 0 do
      if details.Strings[k] <> '' then
        if (PosInsensitive('dir', details.Strings[k]) < 1)
        OR (nodetails.Strings[k] = '.')
        OR (nodetails.Strings[k] = '..') then
         begin
          details.Delete(k);
          nodetails.Delete(k);
         end;

     //if our directory does not exists on the server, create it
     if nodetails.IndexOf(SubDir) = -1
     then FTP.MakeDir(SubDir);
    FINALLY
     FreeAndNil(Details);
     FreeAndNil(nodetails);
    END;
    FTP.ChangeDir(SubDir);   //change into next directory on server
   end;


   procedure uploadDir(dir: string);
   VAR
      s: string;
      List: TStringList;
   begin
     List:= ListDirectoriesOf(dir, FALSE, FALSE);        //iterate through subdirectories
     for s in List DO
      begin
       GoToSubDir(s);
       uploadDir(dir + s + '\');                         //and also locally go into the next subfolder
       FTP.ChangeDirUp;                                  //we have to go one directory up after leaving the recursion
      end;
     FreeAndNil(List);

     List:= ListFilesOf(dir, Filter, FALSE, FALSE);       //iterate through files
     for s in List DO
      begin
        Assert(s > '', 'File name should not be empty!');
        FTP.Put(dir + s, s);                           //if it's only a file, upload it to the current directory;
      end;
     FreeAndNil(List);
   end;


VAR
   subdir, dir: string;
begin
 //does not matter if RemoteDir is like 'dir\dir' or 'dir/dir'
 dir := StringReplace(RemoteDir, '\', '/', [rfReplaceAll]);

 if dir <> '' then
  begin
   if dir[1] = '/' then Delete(dir, 1, 1);     //remove first '/' if there's one
   if dir[Length(dir)] <> '/'  then dir := dir + '/';       // add a '/' at the end

   //loop through our remote-directories
   WHILE Pos('/', dir) > 0 DO
    begin
     SubDir:= system.Copy(dir, 1, Pos('/', dir) - 1);

     //if our directory does not exists on the server, we create it
     GoToSubDir(SubDir);

     //remove first directory from path ('your/directory/subdir/' --> 'directory/subdir/')
     Delete(dir, 1, Pos('/', dir));
    end;
  end;

 dir := LocalDir;
 if dir[Length(dir)] <> '\'
 then dir := dir + '\';

 uploadDir(dir);   // begin the upload
end;



procedure TfrmFTP.Button1Click(Sender: TObject);
begin
 if Connect       {Set parameters for FTP and connect to server }
 then UploadFolderToFtp(ftp, 'c:\test\', RemoteDir, '*.*')
 else SwMessage('Cannot connect to '+ FTP.ServerHOST);
 Disconnect;
end;

-

ListDirectoriesOf&amp; ListFilesOf是一个返回指定文件夹的子目录/文件的函数(它返回非完整路径)

答案 2 :(得分:0)

简单的解决方案是

      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;