6.5 HTTP_Upload 

Besprochene Version: 0.9.1 | Lizenz: LGPL |
Klassendatei(en): HTTP/Upload.php |
HTTP_Upload vereinfacht die Handhabung von Dateien, die mittels eines http-Uploads, sprich mithilfe eines Formulars, an den Server übermittelt wurden. Neben der Tatsache, dass diese Klasse sehr flexibel ist, ist auch noch interessant, dass sie über eine mehrsprachige Fehlerbehandlung verfügt. Ein einfacher Upload könnte aussehen wie in Listing 6.5.
if (false == isset ($_POST["absenden"])) { ?> <form enctype="multipart/form-data" method="post"> Datei: <input type="file" name="userfile" /><br /> <input type="submit" name="absenden" value="Senden"> </form> <?php } else { require_once ('HTTP/Upload.php'); // Neues Objekt mit Sprachangabe fuer Fehler $upload = new HTTP_Upload('de'); // Datei-Objekt auslesen $datei = $upload->getFiles('userfile'); // Ist ein Fehler aufgetreten? if (true === PEAR::isError($datei)) { die ($datei->getMessage()); } // Wurde die Datei hochgeladen? if (true === $datei->isValid()) { // Datei kopieren $dateiname = $datei->moveTo('uploads'); // Konnte die Datei kopiert werden? if (true===PEAR::isError($dateiname)) { die ($dateiname->getMessage()); } else { echo 'Der Upload war erfolgreich'; } } }
Listing 6.5 Upload einer Datei mit PEAR::HTTP_Upload
Wie Sie sehen, ist die Steuerung eines Uploads denkbar einfach. Der Konstruktor bekommt die Information übergeben, in welcher Sprache die Fehlermeldungen ausgegeben werden sollen. Zurzeit werden Englisch (en), Deutsch (de), Französisch (fr), Holländisch (nl), Italienisch (it), Spanisch (es) und brasilianisches Portugiesisch (pt_BR) unterstützt.
Die Methode getFiles() liest die Daten der hochgeladenen Datei aus. Übergeben Sie mehrere Dateien in Form eines Arrays oder mit unterschiedlichen Feldnamen, so muss getFiles() nicht mehrfach aufgerufen werden. Ein Aufruf ohne Parameter liefert Ihnen ein Array mit so vielen HTTP_Upload_File-Objekten, wie Dateien übergeben wurden. Das Formular
Datei 1: <input type="file" name="userfile[A]" /> Datei 2: <input type="file" name="userfile[]" /> Datei 3: <input type="file" name="userfile[]" /> Datei 4: <input type="file" name="datei" />
könnten Sie also so verarbeiten:
$dateien = $upload->getFiles(); foreach ($dateien as $datei) { // Jede Datei kopieren $dateiname = $datei->moveTo('uploads'); // Weiterer Code zur Verarbeitung der Dateien }
Wie erwähnt liefert getFiles() in so einem Fall ein Array zurück. Es handelt sich dabei um ein assoziatives Array, bei dem jeder Feldname, der an PHP übergeben wird, zum Schlüssel des Arrays wird. Im obigen Beispiel könnten die einzelnen Elemente auch über $dateien["userfile[A]"], $dateien["userfile[0]"], $dateien["userfile[1]"] und $dateien["userfile[datei]"] angesprochen werden. Bitte beachten Sie, dass die einzelnen Array-Schlüssel Strings sind.
Die Methode gibt jeweils HTTP_Upload_File-Objekte zurück. Dieser Objekt-Typ unterstützt die Methode isValid(), um zu prüfen, ob der Upload erfolgreich war und alle Daten korrekt übermittelt wurden. Eine Datei, die hochgeladen wurde, wird vom Server zuerst in einem temporären Verzeichnis abgelegt. Aus diesem Ordner muss sie herauskopiert werden, da sie andernfalls gelöscht wird, sobald das Script durchgelaufen ist. Dies übernimmt die Methode moveTo(), die voraussetzt, dass das Zielverzeichnis existiert und die nötigen Schreibrechte zur Verfügung stehen. Ihr wird der Name des Verzeichnisses übergeben, in das die Datei kopiert werden soll. Wenn ich sage, dass die Datei kopiert wird, so ist das nicht ganz korrekt. Genau genommen wird die Datei verschoben. Das kann – insbesondere bei großen Providern – zu Problemen führen, da das temporäre Verzeichnis dort oft auf einer physikalisch anderen Festplatte liegt als das Zielverzeichnis. Ist das der Fall, schlägt die Methode fehl. In einem solchen Fall müssten Sie die Methode entweder überschreiben oder die Datei mithilfe von copy() zu ihrem Ziel transferieren.
In vielen Fällen reichen die besprochenen Methoden schon aus, um eine ausreichende Funktionalität zu bieten. Aber das Paket kann noch einiges mehr. Eine wirklich hilfreiche Methode des HTTP_Upload-Objekts ist setChmod(). Mit ihr können Sie definieren, welchen Zugriffsmodus die Dateien haben sollen, nachdem sie kopiert wurden. Da es sich hierbei um eine Funktion handelt, die nur unter Unix-Betriebssystemen unterstützt wird, hat sie unter Windows keinen Effekt. Die Rechte sollten Sie mit Hilfe einer oktalen Zahl angeben, wobei der Aufbau der Rechtemaske mit der von Unix-Systemen identisch ist. Sollen also alle Dateien für alle Benutzer zum Lesen und Schreiben freigegeben werden, könnten Sie das mit
$upload=new HTTP_Upload(); $upload->setChmod(0666);
festlegen. Standardmäßig nutzt das Paket die Maske 660, so dass der Eigentümer und seine Gruppe Lese- und Schreibrechte haben.
Darüber hinaus unterstützt das HTTP_Upload_File-Objekt noch einige interessante Features. Als Erstes ist hier die Methode getProp() zu nennen, mit der Sie die Eigenschaften einer Datei auslesen können. Rufen Sie sie ohne einen Parameter auf, so liefert sie Ihnen ein Array zurück, das alle Eigenschaften der Datei enthält. Ein solches Array kann beispielsweise so aussehen:
array(8) { ["real"]=> string(16) "bewerbung.doc" ["name"]=> string(16) "bewerbung.doc" ["form_name"]=> string(11) "userfile[0]" ["ext"]=> string(3) "doc" ["tmp_name"]=> string(14) "/tmp/phpO3XFjJ" ["size"]=> int(26112) ["type"]=> string(18) "application/msword" ["error"]=> NULL }
Die ersten beiden Elemente des Arrays enthalten den Originalnamen und den Namen, unter dem die Datei gespeichert werden soll. Danach folgen der Name, den das Formularfeld hatte, das Suffix der Datei, der Name der temporären Datei auf dem Server, die Größe der Datei in Byte sowie der MIME-Type und eine eventuell vorhandene Fehlermeldung. Sie können der Methode auch einen der Array-Schlüssel als String übergeben und erhalten dann nur den damit verknüpften Wert.
Wie Sie nun sicherlich schon vermuten, können Sie die Dateien auch unter einem anderen Namen als dem ursprünglichen abspeichern. Um einer Datei einen neuen Namen zuzuweisen, steht setName() zur Verfügung. Sie bekommt mindestens den neuen Dateinamen übergeben, akzeptiert aber auch noch zwei weitere Strings als Parameter. Der erste String wird dem Dateinamen vorangestellt, wohingegen der zweite an den Namen angehängt wird.
In diesem Zusammenhang möchte ich Ihnen auch nicht nameToSafe() und nameToUniq() verschweigen. Die erste bekommt einen Dateinamen übergeben und konvertiert diesen so, dass alle Sonderzeichen, die problematisch sind, in ungefährliche Zeichen konvertiert werden.
$name=$datei->getProp('name'); // Namen auslesen $extension=$datei->getProp('ext'); // Extension auslesen $name=$datei->nameToSafe($name); // konvertieren $datei->setName($name,"",".$extension"); // neuen Namen setzen
Per Default ist die Länge des Dateinamens auf 250 Zeichen beschränkt. Das können Sie allerdings dadurch verändern, dass Sie als zweiten Parameter die gewünschte Länge als Integer übergeben.
Die Methode nameToUniq() liefert einen Dateinamen zurück, der einmalig ist. Er könnte z. B. so aussehen 9022210413b75410c28bef und wird durch verschiedene Zufallsfunktionen generiert. Ein solcher Dateiname bietet sich immer dann an, wenn Sie verhindern wollen, dass bestehende Dateien überschrieben werden.
Sehr hilfreich kann auch die Methode setValidExtensions() sein. Sie gibt Ihnen die Möglichkeit zu steuern, welche Dateitypen zulässig sind. Sie bekommt ein Array mit Datei-Endungen übergeben und als zweiten Parameter ein deny oder allow. Mit deny werden die Suffixe abgelehnt, die in dem Array definiert sind, wohingegen das allow dafür sorgt, dass nur die entsprechenden Dateitypen akzeptiert werden. Allerdings werden diese Parameter erst von der Methode moveTo() ausgewertet, die im Falle von unzulässigen Dateien ein PEAR_Error-Objekt generiert.