Autor Beitrag
AScomp
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: Fr 20.04.12 18:56 
Hallo,

mit IdFTP ermittle ich über ein DirectoryListing alle Ordner. Hieraus möchte ich eine Ordnerliste erstellen, soweit alles kein Problem.

Allerdings schreibt IdFTP.List auch alle Dateien in das DirectoryListing. Ich kann jetzt zwar über ItemType ermitteln, ob es sich um einen Ordner handelt - damit wird der gesamte Vorgang aber zu langsam.

Habe es auch schon mit List('DIR', false), List('*.', false) und List('*', false) ausprobiert, führt aber alles nicht zum gewünschten Ergebnis.

Meine Frage also: Wie kann ich möglichst schnell alle Ordner des FTP-Servers ermitteln?

Aktuelle Umsetzung (die logischerweise viel zu langsam ist):

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
procedure TFormMain.GetFolders(ScanDir: String);
var
   ListFolders: TStringList;
   xFor: Integer;
begin
     ListFolders := TStringList.Create;
     ListFolders.Sorted := true;

     try
        IdFTP.ChangeDir(ScanDir);
        RzComboBoxSyncFTPFolders.Items.Add(ScanDir);
        IdFTP.List('*', true);

        for xFor := 0 to IdFTP.DirectoryListing.Count - 1 do begin
            if IdFTP.DirectoryListing[xFor].ItemType = ditDirectory then begin
               if (IdFTP.DirectoryListing[xFor].FileName <> '.'and (IdFTP.DirectoryListing[xFor].FileName <> '..'then begin
                  if ScanDir[Length(ScanDir)] = '/' then
                     ListFolders.Add(ScanDir + IdFTP.DirectoryListing[xFor].FileName)
                  else
                     ListFolders.Add(ScanDir + '/' + IdFTP.DirectoryListing[xFor].FileName);
               end;
            end;
        end;

        for xFor := 0 to ListFolders.Count - 1 do
            GetFolders(ListFolders.Strings[xFor]);

     finally
        ListFolders.Free;
     end;
end;


Danke und Gruß

Andy
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 20.04.12 19:03 
Das geht nun einmal nicht so schnell. Der Zeitfaktor ist ja die Anzahl der Anfragen und der Latenz bis darauf die Antwort da ist. Und diese Anzahl lässt sich nun einmal bei dem Protokoll nicht reduzieren, da der Serverkeine rekursive Liste liefert. ;-)
AScomp Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: Fr 20.04.12 19:11 
Darum ja die Frage, ob man das Listing nicht so generieren kann, dass von vornherein nur Ordner enthalten sind. Das würde den Vorgang nämlich stark beschleunigen.

Das große Problem ist ja, dass ich über das aktuelle Listing auch die Details abfragen muss (ADetails = true im List-Aufruf), um feststellen zu können, ob es eine Datei oder ein Ordner ist.

Könnte ich die ADetails ausschalten (weil das Listing eben von vornherein nur Ordner zurückgibt), dann sollte das den Vorgang enorm beschleunigen.

Aber wie ich aus deinem Beitrag herauslese, gibt es einen solchen Filter bzw. einen passenden FTP-Befehl hierfür einfach nicht.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 21.04.12 05:55 
Ich habe mal ein wenig experimentiert:
Bei rund 1000 abzurufenden Ordnern habe ich es einmal mit und einmal ohne Details versucht (die Ordnerliste hatte ich vorher einmal ermittelt und abgespeichert). Mit Details hat es 340-364 Sekunden gedauert, ohne 328-335 Sekunden. Da ich das aufgrund der Zeitspanne nur zweimal getestet habe (daher jeweils die zwei Werte), kann die Abweichung auch Zufall gewesen sein.

Es ist auf jeden Fall kein so großer Unterschied wie du die ganze Zeit vermutest.
Wie ich schon sagte: Der Zeitfaktor ist die Anzahl der Anfragen und der Latenz bis darauf die Antwort da ist. Ob du nun LIST oder NLST benutzt, ist dabei gar nicht so relevant, da sowohl Server als auch Client diese Daten sehr schnell verarbeiten können. ;-)
AScomp Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: Sa 21.04.12 14:54 
Es geht ja nicht nur um die Details, sondern primär darum, ob das DirectoryListing nur Ordner enthalten kann.

Du siehst ja schon alleine am Lesen von ganzen Verzeichnisbäumen unter Windows mit SearchRec und FindNext, dass richtig gesetzte Filter enorm viel Zeit einsparen.

Allerdings scheint es wirklich keine Lösung hierfür zu geben bei FTP-Servern. Darum habe ich jetzt also doch eine TreeComboBox verwendet, die eben immer wieder nachlädt, sobald ein Knoten geöffnet wird.

Gruß

Andy
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 21.04.12 16:26 
Schau dir doch einfach mal andere FTP-Tools wie FileZilla an. :zwinker:

Ich mache das in der Regel ähnlich wie dort:
Wenn ich einen Ordner im Baum erweitere, werden die Unterordner abgerufen. Zudem lade ich im Hintergrund jeweils die Unterordner der gerade angezeigten Knoten vor. Auf diese Weise geht das sehr schnell und mit Baum. (So mache ich es im Übrigen auch mit lokalen Verzeichnissen für einen Verzeichnisbaum.)
AScomp Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: Sa 21.04.12 17:15 
Ja, wie gesagt - genauso mache ich es jetzt ja auch.

Allerdings entfällt dann die Möglichkeit einer Listbox, ich habe stattdessen jetzt eben eine TreeCombo von LMD genommen.

Ich lade allerdings immer zwei Level, um auch die Knoten richtig zu setzen (falls Unterordner, Knotenpunkt anzeigen, ansonsten keinen Knotenpunkt erstellen).