Home » Tutorials » Netzwerk und Internet » Indy

Indy

FTP (TIdFTP)

FTP allgemein

FTP, das File Transfer Protocol, basiert auf TCP/IP und dient der Dateiübertragung zwischen zwei Rechnern. Einige Betreiber bieten Dateien jedem per FTP zum Download an, manche ermöglichen auch den Upload. Hierbei handelt es sich anonymes FTP, wofür weder Benutzername noch Passwort nötig sind. Jeder, der eine Website verwaltet, benötigt das dagegen.
Bei FTP werden zwischen Client und Server zwei Verbindungen aufgebaut. Die eine steuert die Verbindung, die andere dient der eigentlichen Datenübertragung.
Siehe auch RFC 959 File Transfer Protocol, Oktober 1985

IdFTP

IdFTP ist eine Client-Komponente, die Kontakt zu einem Server aufnehmen. Außer dem Dateitransfer ermöglicht sie die Anzeige aller Dateien und Verzeichnisse auf dem Server sowie diverse Dateioperationen (Dateien löschen, Verzeichnis anlegen usw.).
Einiges davon demonstriert eine kleine Beispielanwendung:


Folgende wichtige Methoden/Eigenschaften kommen dabei zum Einsatz:

Verbindung zum Server aufbauen

    IdFTP1.Host := edHost.Text;
    IdFtp1.Username := edUser.Text;
    IdFtp1.Password := edPassword.Text;
    IdFtp1.Connect;

Verzeichnis wechseln

Der Parameter gibt den Namen des Unterverzeichnisses an, in das gewechselt werden soll. Soll dagegen ein Verzeichnis nach oben gewechselt werden, ist die Methode ChangeDirUp zu verwenden.

IdFtp1.ChangeDir(edCurrentDir.Text);

Übertragungsmodus einstellen

Lediglich reine Text-Dateien können im ASCII-Modus übertragen werden. Bei allem anderen ist der Binärmodus vorzuziehen. Die Konstanten ftBinary und ftASCII sind in der Unit IdFTPCommon zu finden.

  IdFTP1.TransferType := ftASCII;
  IdFTP1.TransferType := ftBinary;

Verzeichnis auf dem Server anlegen

Der Parameter gibt den Namen des Verzeichnisses an, das an der aktuellen Stelle als Unterverzeichnis angelegt werden soll.

IdFTP1.MakeDir(Directory);

Aktuellen Server-Verzeichnisinhalt in Listbox anzeigen

Zum Auslesen eines Verzeichnisinhalts wird die Methode List verwendet, die in verschiedenen Varianten existiert. Am flexibelsten ist die Variante ohne Parameter. Anschließend findet man alle Daten in IdFtp1.DirectoryListing. Dabei handelt es sich um eine Liste von TIdFtpListItems, über die man iterieren kann. Jedes Element besitzt z.B. die Eigenschaft FileName, die man in eine ListBox einfügen kann:

var
  I: Integer;
begin
  ListBox1.Clear;
  if IdFTP1.Connected then
  begin
    IdFTP1.List();
    for I := 0 to IdFtp1.DirectoryListing.Count - 1 do
      ListBox1.Items.Add(IdFtp1.DirectoryListing.Items[I].FileName);
  end;

Datei downloaden

Der erste Parameter ist der Dateiname auf dem Server, der zweite der Name der Zieldatei auf der lokalen Platte, und der Boolean-Parameter gibt an, ob die Datei überschrieben werden soll, wenn sie bereits existiert.

IdFTP1.Get(Name, SaveDialog1.FileName, true);

Datei uploaden

Der erste Parameter der Methode Put gibt den Namen (inkl. Verzeichnis) der hochzuladenden Datei auf der lokalen Platte an, der zweite den reinen Dateinamen, den die Datei auf dem Server bekommen soll.

IdFTP1.TransferType := ftBinary;
IdFTP1.Put(OpenDialog1.FileName, ExtractFileName(OpenDialog1.FileName));

Vom Server löschen

Der Parameter ist der Name des zu löschenden Unterverzeichnisses bzw. der zu löschenden Datei.

IdFTP1.RemoveDir(Name); //löscht ein Verzeichnis
IdFTP1.Delete(Name);    //löscht eine Datei

Verbindung zum Server beenden

Zum Trennen der Verbindung wird die Methode Disconnect verwendet. Die immer noch existierende Methode Quit soll nicht mehr zum Einsatz kommen (deprecated).

IdFtp1.Disconnect;

Fortschrittsanzeige

Will man in einer Anwendung den Fortschritt eines Up- oder Downloads anzeigen, können die Ereignisse OnWorkBegin und OnWork von IdFTP verwendet werden. In OnWorkBegin, das einmal zu Beginn eines Transfers ausgelöst wird, erhält man den Parameter AWorkCountMax. Auf diesen Wert kann man den Maximalwert einer ProgressBar setzen:

procedure TForm1IdFTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCountMax: Int64);
begin
  ProgressBar1.Max := AWorkCountMax;
  ProgressBar1.Position := 0;
end;

In OnWork, das dann während des Dateitransfers nach jedem Datenblock ausgelöst wird, kann dann die Breite des Fortschrittsbalkens vergrößert werden. In dieser Methode lässt sich auch die Übertragungsgeschwindigkeit errechnen:

procedure TForm1.IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Int64);
Var
  S: String;
  TotalTime: TDateTime;
  H, M, Sec, MS: Word;
  DLTime: Double;
begin
  //Errechnen der Transfergeschwindigkeit:
  TotalTime :=  Now - STime;
  DecodeTime(TotalTime, H, M, Sec, MS);
  Sec := Sec + M * 60 + H * 3600;
  DLTime := Sec + MS / 1000;
  if DLTime > 0 then
    AverageSpeed := (AWorkCount / 1024) / DLTime;
  S := FormatFloat('0.00 KB/s', AverageSpeed);
  case AWorkMode of
    wmRead: StatusBar1.Panels[1].Text := 'Download speed ' + S;
    wmWrite: StatusBar1.Panels[1].Text := 'Uploade speed ' + S;
  end;

  //Aktualisieren der Fortschrittsanzeige:
  ProgressBar1.Position := AWorkCount;
end;

STime ist dabei eine Variable vom Typ TDateTime, der zu Beginn der Übertragung (Ereignis OnWorkBegin) die aktuelle Zeit (now) zugewiesen werden muss. Dadurch kann in obiger Ereignisbehandlungsroutine geprüft werden, wie lange die Übertragung bereits dauert.

Beispielprogramm