procedure TForm1.DownLoadDir(LocalPath, ServerPath: string);
var
   i,count1:integer;
   att:TIdDirItemType;
   FileList  : TStrings;
   Name{, Line}: String;
   ss:string;
   BytesToTransfer:integer;
   j:integer;
   s:string;
 
begin
  // begin
    TRY       FileList := TStringList.Create;
       IdFTP1.ChangeDir(serverpath);
       //ChageDir(serverpath);
       Application.ProcessMessages;
       if AnsiLastChar(serverpath) <> '/' then
         serverpath := serverpath + '/';
       if AnsiLastChar(localpath) <> '\' then
         localpath := localpath + '\';
       if not DirectoryExists(localpath+serverpath) then ForceDirectories(localpath+serverpath);
       IdFTP1.List(FileList);
       Application.ProcessMessages;
       count1:=IdFTP1.DirectoryListing.Count;
    
       for i:=0 to count1-1  do
       begin
          ss:=IdFTP1.DirectoryListing.Items[i].FileName;
          att:=IdFTP1.DirectoryListing.Items[i].ItemType;
        if (att<>ditDirectory) then
        begin
          if not DirectoryExists(localpath+serverpath) then ForceDirectories(localpath+serverpath);
          BytesToTransfer := IdFTP1.Size(ss);
          if IsFileInUse(ss)=False then
          IdFTP1.Get(ss,localpath+serverpath+ss,true)
          else Exit;
          Application.ProcessMessages;
          Label1.Caption:='已下载:'+ss;
          Label1.Update;
         end ;
         end;
            for i:=0 to count1-1 do
      begin
          ss:=IdFTP1.DirectoryListing.Items[i].FileName;
          att:=IdFTP1.DirectoryListing.Items[i].ItemType;
          //BytesToTransfer := IdFTP1.Size(ss);
          if (att=ditDirectory) and (ss <> '.') AND (ss <> '..') then
          begin
          Name := ss;
          if not DirectoryExists(localpath+serverpath+Name) then
          ForceDirectories(localpath+serverpath+Name);
        DownLoadDir(localpath+serverpath,Name);
          Application.ProcessMessages;          end;      end;        //ChageDir('..');//这句是返回前一个目录,写的另一个函数,可以用IdFTP1.ChangeDir替换
          IdFTP1.ChangeDir('..');
         //IDFTP1.ChangeDirUp;
          Filelist.Free;
         //BytesToTransfer := IdFTP1.Size(ss);
   except
   end;
end;是个递归写文件目录的程序;问题是一个目录下有两个目录的时候。在ss:=IdFTP1.DirectoryListing.Items[i].FileName;里报错。list index out of bound;
但是去掉递归调用  DownLoadDir(localpath+serverpath,Name); 这句就不报错。而且两个文件夹都能下载;但这不是我要求的;

解决方案 »

  1.   

    你首先应该判断这个是否为文件夹再处理
    FTPClient.DirectoryListing.Items[i].ItemType = ditDirectory
      

  2.   

    这个早就判断了。 if (att<>ditDirectory) then 这句已经判断了。在第二个循环里if (att=ditDirectory) and (ss <> '.') AND (ss <> '..') then就会进入递归创建本地文件夹
      

  3.   

    报错应该出在第二个循环里面的那句话上。因为,你的idftp1是个全局变量,递归进去的时候,idftp1的相关信息都被修改了,出来后再访问的信息已经不是递归前的了。改进方法:
    1.idftp1变为局部变量,动态创建
    2.复制目录列表到另一个局部变量,程序改为查询那个局部变量。
      

  4.   

    好像有点道理。
    改进方法:
    1.idftp1变为局部变量,动态创建
    2.复制目录列表到另一个局部变量,程序改为查询那个局部变量。1我会。
    2的话是什么意思。麻烦写点东西或者伪代码什么的
    万分感谢
      

  5.   

    var
            mList: TIdFtpListItems;//前面需要uses IdFTPList
    begin
            .......
            mList := TIdFtpListItems.Create;
            mList.Assign(idftp1.DirectoryListing);
            .......
            mList.Destroy;
    end;
    Assign后,程序里面直接使用mList,而不要用idftp1.DirectoryListing