delphi 如何通过FTP填充树视图

ee7vknir  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(163)

方案

我试图复制标准的方法,从文件夹结构中的目录/文件夹填充树视图,从根目录开始,但使用IdFTP从远程服务器而不是我的本地硬盘驱动器获得结构。我希望结果看起来类似于Filezilla这样的客户端。
我使用了来自瑞士 Delphi 中心的this标准代码(用于显示我的硬盘结构),然后将其修改为使用IdFTP.ChangeDir(Directory)和IdFTP.List,而不是FindFirst()和FindNext()。

问题

我似乎已经得到了自己在一个混乱,因为它是不正确的'展开'递归,这样,一旦它遍历了远程服务器上的/cpanel/cashes/config目录,它不返回和遍历所有其他目录挂在根目录,但退出过程没有显示任何其他内容。此外,它似乎没有显示所有的顶级文件夹,但这可能只是由于顺序IdFTP. List返回它们的格式为
谁能告诉我我做错了什么?
如果您还能告诉我应该如何显示根(/),那将非常有帮助
(我已经注解掉了显示非目录,因为我在这个阶段只想要文件夹)

我期望看到的内容复制自Filezilla

我所看到的在 Delphi 中使用Ttreeview

我的代码

procedure TForm2.Button1Click(Sender: TObject);
var StartingDir : string;
begin
TreeView1.Items.BeginUpdate;
try
    StartingDir :=    '/';
    Screen.Cursor := crHourGlass;
    TreeView1.Items.Clear;
    FTPconnect;  //procedure to connect to remote server
    GetDirectories(TreeView1, StartingDir, nil, True);
    FTPDisconnect; //procedure to disconnect from remote server
finally
    TreeView1.Items.EndUpdate;
    Screen.Cursor := crDefault;
end;
end;

procedure TForm2.GetDirectories(Tree: TTreeView; Directory: string; Item: TTreeNode; IncludeFiles: Boolean);
var
  ItemTemp: TTreeNode;
  DirItemType : TIdDirItemType  ;
  Filename , NewStartingDirectory: string;
  i : Integer;
begin
  Tree.Items.BeginUpdate;
  IdFTP.ChangeDir(Directory);
  IdFTP.List;      //get directory of remote folder
  i:=0;
  repeat
     DirItemType := IdFTP.DirectoryListing[I].ItemType;
     Filename := IdFTP.DirectoryListing[I].FileName;
     If (DirItemType = ditDirectory) and (Filename <> '.') and (Filename <> '..')then
        begin
        if DirItemType = ditDirectory then
              Item := Tree.Items.AddChild(Item, Filename);
        ItemTemp := Item.Parent;
        if Directory = '/' then
            NewStartingDirectory := Directory  + Filename
        else
            NewStartingDirectory := Directory + '/' +Filename;
        GetDirectories(Tree, NewStartingDirectory, Item, IncludeFiles);
        Item := ItemTemp;
        end
     else 
        if IncludeFiles then
           begin  //this bit commented out as we only want to see directories
//         if (Filename <> '.') and (Filename <> '..') then
//         Tree.Items.AddChild(Item, Filename);
           end;
     inc(i);
  until i = IdFTP.DirectoryListing.Count;
  Tree.Items.EndUpdate;
end;

瑞士Delhpi中心代码(用于比较)

procedure TForm1.Button1Click(Sender: TObject);
var
  Node: TTreeNode;
  Path: string;
  Dir: string;
begin
  Dir := 'c:\temp';
  Screen.Cursor := crHourGlass;
  TreeView1.Items.BeginUpdate;
  try
    TreeView1.Items.Clear;
    GetDirectories(TreeView1, Dir, nil, True);
  finally
    Screen.Cursor := crDefault;
    TreeView1.Items.EndUpdate;
  end;
end;

procedure TForm1.GetDirectories(Tree: TTreeView; Directory: string; Item: TTreeNode; IncludeFiles: Boolean);
var
  SearchRec: TSearchRec;
  ItemTemp: TTreeNode;
begin
  Tree.Items.BeginUpdate;
  if Directory[Length(Directory)] <> '\' then Directory := Directory + '\';
  if FindFirst(Directory + '*.*', faDirectory, SearchRec) = 0 then
  begin
    repeat
      if (SearchRec.Attr and faDirectory = faDirectory) and (SearchRec.Name[1] <> '.') then
      begin
        if (SearchRec.Attr and faDirectory > 0) then
          Item := Tree.Items.AddChild(Item, SearchRec.Name);
        ItemTemp := Item.Parent;
        GetDirectories(Tree, Directory + SearchRec.Name, Item, IncludeFiles);
        Item := ItemTemp;
      end
      else if IncludeFiles then
        if SearchRec.Name[1] <> '.' then
          Tree.Items.AddChild(Item, SearchRec.Name);
    until FindNext(SearchRec) <> 0;
    FindClose(SearchRec);
  end;
  Tree.Items.EndUpdate;
end;

我已经看过SO here-太复杂和错误的语言和here-类似于瑞士 Delphi 中心和here-错误的语言,不知道它在做什么。
如果使用TlistView更好,您能给我看一下使用它的等效代码吗?

ig9co6j1

ig9co6j11#

未测试:

  • 我将TIdFTP变量设置为参数,因为TTreeView也是一个参数,并且应该保持一致,而不是过时。
  • 使用for循环而不是repeat until
  • 在不使用IncludeFiles时将其删除。
  • 消除奇怪的逻辑以始终获取新TreeNode的父节点。
  • 不再锁定TreeView-在调用此方法之前执行一次此操作,并在调用后解锁它-否则,您将徒劳地执行数十次此操作。

1.基本逻辑是如我在注解中所写的:
1.将所有文件夹字符串存储到您自己的列表中,并避免此时出现递归。
1.修复要连接一次的路径,而不是循环的每次迭代。
1.遍历该列表进行递归--此时FTP的状态无关紧要,您不会在不同级别上弄乱列表。
1.当然,释放所创建的StringList示例。

procedure TForm2.GetFolders
( Ftp: TIdFTP  // The source, from which we read the content
; Tree: TTreeView  // The destination, which we want to fill
; ParentNode: TTreeNode  // Node under which all new child nodes should be created
; Path: String  // Starting directory
);
var
    NewNode: TTreeNode;  // New child in the tree
    Filename: String;  // Check against unwanted folder entries
    i: Integer;  // Looping over both lists
    sl: TStringList;  // Collect folders only
begin
    FTP.ChangeDir( Path );
    FTP.List;  // Entire remote listing

    sl:= TStringList.Create;  // Collect all entries we're interested in
    try
        for i:= 0 to FTP.DirectoryListing.Count- 1 do begin  // For each entry
            Filename:= FTP.DirectoryListing[i].FileName;
            if  (FTP.DirectoryListing[i].ItemType= ditDirectory)  // Only folders
            and (Filename<> '.')
            and (Filename<> '..') then begin
                sl.Add( Filename );  // Only the name, not the full path
            end;
        end;

        // Do this only once
        if Path<> '/' then Path:= '/'+ Path+ '/';

        for i:= 0 to sl.Count- 1 do begin  // All collected folders
            NewNode:= Tree.Items.AddChild( ParentNode, sl[i] );  // Populate tree
            GetFolders( Ftp, Tree, NewNode, Path+ sl[i] );  // Recursion of folder name + current path
        end;
    finally
        sl.Free;
    end;
end;

未测试,但应编译。

相关问题