Entwickler-Ecke

Internet / Netzwerk - IdFTP: Alle Ordner ermitteln


AScomp - Fr 20.04.12 17:56
Titel: IdFTP: Alle Ordner ermitteln
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):


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 - Fr 20.04.12 18: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 - Fr 20.04.12 18: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 - Sa 21.04.12 04: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 - Sa 21.04.12 13: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 - Sa 21.04.12 15: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 - Sa 21.04.12 16: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).