Automatisch Daten via FTP importieren

Nicht immer können wir auf komfortable Schnittstellen zurück greifen, wenn wir Daten aus externen Quellen importieren wollen. Manchmal müssen wir die Daten auf andere Weise herunterladen. Heute zeige ich Euch, wie Ihr mit Daten umgehen könnt, die Euch nur per FTP zur Verfügung gestellt werden. Hintergrund ist ein aktuelles Projekt, bei dem ein Kunde Daten regelmäßig in einen per FTP zugänglichen Ordner exportieren wollte.

Eine Datei über FTP herunter zu laden ist unter PHP nicht besonders schwierig. Wir benötigen dafür nur den $host mit dem wir uns verbinden wollen, sowie die Zugangsdaten für den Server ($username und $password). Eine Verbindung mit dem Server stellen wir dann so her:

$connection = ftp_connect($host);
if (!$connection) {
  throw new Exception('Unable to connect to host: ' . $host);
}

if (!@ftp_login($connection, $username, $password)) {
  throw new Exception('Unable to login with username: ' . $username);
}

if (!@ftp_pasv($connection , TRUE)) {
  throw new Exception('Unable to activate passive mode.');
}

Beachtet, dass wir hier explizit den Passive Mode von FTP aktivieren. Je nach Eurer PHP-Konfiguration ist der Default unter Umständen ein anderer und meiner Erfahrung nach führt der Active Mode oft zu Problemen. Eine einzelne Datei können wir dann mit ftp_get() herunterladen ($filepath ist dabei der Dateipfad auf dem FTP-Server):

ob_start();
$result = ftp_get($connection, 'php://output', $filepath, FTP_BINARY);
$contents = ob_get_contents();
ob_end_clean();

if (!$result) {
  throw new Exception('Unable to read file: ' . $filepath);
}

Über ob_get_contents() schneiden wir die heruntergeladenen Daten mit und speichern sie in der Variable $contents zwischen. Ob wir die Daten dann anschließend in einer Datei auf unserem Server speichern, in der Datenbank ablegen oder direkt verarbeiten, überlasse ich an dieser Stelle Euch.

Ihr könntet nun dieses Skript in regelmäßigen Abständen abfeuern und jeweils Daten vom FTP-Server laden und importieren. Wie Ihr Euch vorstellen könnt, ist so ein Download und Import aber unter Umständen ein langwierigere Geschichte. Wir sollten also unsere Ressourcen schonen und den Download nur durchführen, wenn überhaupt neue Daten vorhanden sind.

Auch das lässt sich relativ einfach über FTP realisieren. Über ftp_mdtm() lässt sich nämlich das letzte Änderungsdatum einer Datei feststellen. Dieses können wir dann mit unserem Datenstand vergleichen. Den Timestamp finden wir dann zum Beispiel so heraus:

$filemtime = ftp_mdtm($connection, $filepath);
if ($filemtime === -1) {
  throw new Exception('Unable to determine filemtime for: ' . $filepath);
}

Wer sich darunter noch nicht soviel vorstellen kann, dem hilft vielleicht das Skript in seiner Gänze zu betrachten. Wie immer bin ich sehr an Eurer Meinung interessiert. Und viel Spaß beim Ausprobieren.

// Zuerst stellen wir eine Verbindung her.
$connection = ftp_connect($host);
if (!$connection) {
  throw new Exception('Unable to connect to host: ' . $host);
}

if (!@ftp_login($connection, $username, $password)) {
  throw new Exception('Unable to login with username: ' . $username);
}

if (!@ftp_pasv($connection , TRUE)) {
  throw new Exception('Unable to activate passive mode.');
}

// Dann vergleichen wir den Timestamp der Daten auf dem FTP-Server mit unserem
// eigenem Datenstand. $last_import soll dabei unser eigener Datenstand sein.
$filemtime = ftp_mdtm($connection, $filepath);
if ($filemtime === -1) {
  throw new Exception('Unable to determine filemtime for: ' . $filepath);
}

// Wenn die Daten auf dem Server neuer sind, führen wir den Download durch.
if ($filemtime > $last_import) {
  ob_start();
  $result = ftp_get($connection, 'php://output', $filepath, FTP_BINARY);
  $contents = ob_get_contents();
  ob_end_clean();

  if (!$result) {
    throw new Exception('Unable to read file: ' . $filepath);
  }

  // Nun speichern wir die Daten zwischen, importieren sie oder was auch immer.
  // ...
}

Noch keine Kommentare vorhanden.