Datei hochladen mit PHP
In diesem Tutorial wollen wir Schritt für Schritt zu einer funktionierenden Dateiupload-Funktion für eine Website mit Unterstützung mehrerer Dateien gelangen. Dazu wird ein modifiziertes einfaches Formular verwendet und in eine bestehende XHTML-Seite integriert.
Codebeispiel 1: einfaches Formular
<form action=”datei.php” method=”post”>
<p>Name: <input type=”text” name=”name” /></p>
<p><input type=”submit” value=”Abschicken” /></p>
</form>Codebeispiel 2: Formular zum Dateiupload
<form action=”datei.php” method=”post” enctype=”multipart/form-data”>
<p>Datei: <input type=”file” name=”userfile” /></p>
<p><input type=”submit” value=”Abschicken” /></p>
</form>Wir können erkennen, dass die beiden Formulare sich in zwei wesentlichen Punkten unterscheiden: Zum einen enthält der form-Tag das Attribut enctype=”multipart/form-data”, und zum anderen ist der Typ des input-Feldes ein anderer als gewöhnlich. Das Attribut enctype in einem form-Tag muss dann mit multipart/form-data gesetzt werden, wenn dem Webserver mitgeteilt werden soll, dass Dateien hochgeladen werden sollen. Dies veranlasst den Webserver dann, die Datei(en) in ein temporäres Verzeichnis zu kopieren sowie die zugehörigen Informationen in dem Superglobal-Array $_FILES (in PHP < 4.1.0: $HTTP_POST_FILES) zu speichern, welches dann mit einem PHP- oder CGI-Script ausgelesen werden kann. Wir wollen uns aber hier auf die PHP-Variante beschränken, da dies im Privatbereich die verbreitetere ist.
Nachdem wir nun also mit Hilfe des Codebeispiels 2 ein einfaches Upload-Formular erstellt haben, machen wir uns nun an das Script zum Auslesen, welches wir in unserem Beispiel datei.php ganannt haben. Dafür ist natürlich ein Webserver mit PHP-Unterstützung notwendig. In dem Array $_FILES finden wir unter dem Schlüssel “userfile” (dieser Schlüssel entsprich dem Namen des input-Feldes) alle Informationen zu der hochgeladenen Datei:
$_FILES[”userfile”][”name”]: Der originale Dateiname
$_FILES[”userfile”][”type”]: Falls vorhanden, der MIME-Type der Datei, z.b. text/plain oder image/gif
$_FILES[”userfile”][”size”]: Dateigröße in Bytes
$_FILES[”userfile”][”tmp_name”]: Dateiname der Datei auf dem Server (von hier muss sie später kopiert werden, sonst wird sie nach Beendigung des Scripts gelöscht)
$_FILES[”userfile”][”error”]: “Status-Code” für den Upload (PHP >= 4.0.2, Erklärung folgt weiter unten)
Mit Hilfe dieser Informationen können wir jetzt die Datei aus dem temporären Verzeichnis kopieren. Hier gibt es zwei unterschiedliche Methoden: einmal mit copy() in PHP < 4.0.3 und einmal mit move_uploaded_file() in PHP >= 4.0.3
Codebeispiel 3: Verarbeitung der Datei in PHP >= 4.0.3
<?php
$dir_upload = “/var/www/files/upload/”; //Pfad auf dem Server, wo die Datei gespeichert werden soll (PHP muss Schreibrechte besitzen!)
if (move_uploaded_file($_FILES[“userfile”][“tmp_name”], $dir_upload.$_FILES[“userfile”][“name”])) { //Kopiervorgang
echo “File ”.$_FILES[“userfile”][“name”].“ erfolgreich hochgeladen.”;
} else {
echo “Fehler beim Upload! Info:”;
echo “<pre>”; var_dump($_FILES); echo “</pre>”;
}
?>[php]
Codebeispiel 4: Verarbeitung der Datei in PHP < 4.0.3
[php]<?php
$dir_upload = “var/www/files/upload/”;
if (
copy($HTTP_POST_FILES[“userfile”][“tmp_name”], $dir_upload.$HTTP_POST_FILES[“userfile”][“name”])) {
echo “Erfolg.”;
} else {
echo “Fehler beim Upload. Sind alle Rechte richtig gesetzt?”;
}
?>Letztere Variante ist allerdings nicht empfehlenswert, da sie keine Prüfung der Datei enthält, ob sie auch wirklich hochgeladen wurde.
So, jetzt haben wir also schon eine Datei hochgeladen und an einen anderen Ort kopiert. Nun kann man das Script natürlich erweitern, wie Sortierung nach Dateityp oder Aussortierung von zu kleinen/zu großen Dateien. Doch das soll nicht Gegenstand dieses Tutorials sein. Viel interessanter ist noch die Frage, wie wir jetzt auch mehrere Dateien auf einmal hochladen können. Zuerst sei erwähnt, dass das Hochladen mehrerer Dateien mit einem input-Feld oder gar von Verzeichnissen nicht möglich ist. Die einzige Möglichkeit ist, mehrere input-Felder zu bemühen.
info: Es ist sehr wichtig, dass ihr eine Prüfung einbaut, welche überprüft ob da vielleicht eine PHP Datei hochgeladen wird! Ansonsten hat in wenigen Minuten jeder Zugriff auf den Server / Webspace. Einfache Methode ist auch eine zusätzliche Dateierweiterung zu verwenden.
Codebeispiel 5: Formular mit mehreren Dateien
<form action=”datei.php” method=”post” enctype=”multipart/form-data”>
<p>Datei 1: <input type=”file” name=”userfile1″ /></p>
<p>Datei 2: <input type=”file” name=”userfile2″ /></p>
<p>Datei 3: <input type=”file” name=”userfile3″ /></p>
<p><input type=”submit” value=”Abschicken” /></p>
</form>Hier wird einfach das Array $_FILES “erweitert”:
$_FILES[”userfile1″] ist das Array für die erste Datei und enthält die gleiche Struktur wie das oben verwendete $_FILES[”userfile”].
$_FILES[”userfile2″] für die zweite Datei und so weiter.
Zum Auslesen im PHP-Script empfiehlt sich die Funktion foreach(), welche ein Array automatisch Schritt für Schritt abarbeitet. In unserem Beispiel entspricht die Variable $datei jeweils dem Array $_FILES[”userfileX”]. Die Idee dahinter ist, dass ja bei mehreren Dateien das Script oben nur mehrmals für verschiedene Dateinamen ausgeführt werden muss.
Codebeispiel 6: Auslesen der Dateien mit PHP >= 4.0.3
<?php
$dir_upload = “/var/www/files/upload”; //Pfad auf dem Server, wo die Datei gespeichert werden soll (PHP muss Schreibrechte besitzen!)
foreach($_FILES as $datei) {
if ($datei[“error”] == 0) {
if (move_uploaded_file($datei[“tmp_name”], $dir_upload.$datei[$key][“name”])) { //Kopiervorgang
echo “File ”.$datei[“name”].“ erfolgreich hochgeladen.”;
} else {
echo “Fehler beim Upload! Info:”;
echo “<pre>”; var_dump($_FILES); echo “</pre>”;
exit;
}
}
}
?>Codebeispiel 7: Auslesen der Dateien mit PHP < 4.0.3
<?php
$dir_upload = “var/www/files/upload/”;
foreach($HTTP_POST_FILES as $datei) {
if ($datei[“error”] == 0) {
if (copy($datei[“tmp_name”], $dir_upload.$datei[“name”])) {
echo “Erfolg.”;
} else {
echo “Fehler beim Upload. Sind alle Rechte richtig gesetzt?”;
exit;
}
}
}
?>Hier wird bei einem Fehler beim Upload die Schleife abgebrochen, um keine weiteren Schäden zu verursachen. Natürlich kann man auch in diese Schleife für jede Datei Filter einbauen oder jegliche gewünschte Aktion ausführen lassen. Auch ausführliche Fehleranalysen anhand der Errorcodes können erstellt werden. Zum Beispiel könnte man nur Files mit Error-Code 0 kopieren lassen, was für einen erfolgreichen, korrekten Upload steht. Dagegen bei einem Error-Code 1 könnte man eine detaillierte Fehlermeldung zurückgeben, dass die maximale Uploadgröße überschritten wurde. Außerdem ist es möglich (aber unsicher), vor dem File-Inputfeld ein
<input type=”hidden” name=”MAX_FILE_SIZE” value=”maximale_groesse_der_datei_in_bytes” />einfügen. Wird diese Größe überschritten, gibt PHP einen Fehlercode 2 zurück. Ebenfalls hilfreich gegen fehlerhafte Uploads ist der Errorcode 3: Er signalisiert unvollständige Uploads. Um Fehlermeldungen für leere Input-Felder zu verhindern, kann man eine Überprüfung einbauen, ob überhaupt eine Datei hochgeladen wurde. Wenn nicht, ist der Error-Code 4. In neueren Versionen gibt es noch die Fehler 6 und 7 (kein temporäres Verzeichnis, Schreibfehler).