Autor |
Beitrag |
AScomp
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: 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):
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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: 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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: 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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 21.04.12 16:26
Schau dir doch einfach mal andere FTP-Tools wie FileZilla an.
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 
      
Beiträge: 162
Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
|
Verfasst: 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).
|
|
|