Wer kennt es nicht, man meldet sich in einem Portal an, man gibt sich einen Nutzernamen und lädt ein Profilbild hoch. Wie das funktioniert das Hochladen von Dateien ((PHP) Upload) und welche Technik steckt dahinter ? Die hochzuladenden Dateien (wie ein Profilbild) werden von dem Browser (Firefox, Chrome, Safari, Edge etc.) im Content einer HTTP Anfrage an den Webserver der entsprechenden Webseite gesendet. Die HTTP Anfrage wird von dem Webserver verarbeitet und z.B. an die Scriptsprache PHP weitergeleitet. PHP verarbeitet mit $_POST und $_FILES die empfangene Anfrage und stellt sie dem Programm bereit. Ein Webserver funktioniert grundsätzlich wie der Computer; die empfangenden Dateien werden in irgendeinem Ordner-System ablegt.
Upload einer einzelnen Datei
Für den Upload einer Datei benötigen wir ein HTML-Formular. Das Formular ist erstmal relativ einfach, uns interessiert die Technik dahinter. Sobald man den Button „Durchsuchen…“ klickt, wird der Dateibrowser mit der Dateiauswahl geöffnet.
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 |
<html> <head> <meta charset="utf-8" /> <title>Upload einer Datei</title> </head> <body> <h1>Upload einer Datei</h1> <hr /> <form method="POST" enctype="multipart/form-data"> <label>Bitte wählen sie eine Datei zum hochladen aus.</label> <input name="datei" type="file" /> <br /> <input type="submit" value="Datei hochladen" /> </form> </body> </html> |
Wichtig ist, dass das Formular im Form-Tag enctype="multipart/form-data enthält, sonst können keine Dateien hochgeladen werden. In folgenden Schritt erweitern wir unser Script mit PHP, so dass die Werte (Dateigröße, Dateiformat) der hochgeladenen angezeigt werden. <input name="datei" type="file" /> Der Input-Tag ermöglicht das Hochladen (Upload) einer Datei. Zum Nachmachen verwendet ihr am Besten das freie Programm xampp als Webserver und legt im Verzeichnis htdocs einen neuen Ordner „upload“ an. In dem Ordner „upload“ legt ihr die Datei „index.php“ an und speichert den Code für das Formular in der Datei.
PHP: Upload einer Datei
Die große Magie passiert durch die Verarbeitung der empfangen Datei durch die Scriptsprache PHP.
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 32 33 34 35 36 37 38 39 40 41 |
<html> <head> <meta charset="utf-8" /> <title>Upload einer Datei</title> </head> <body> <h1>Upload einer Datei</h1> <hr /> <form method="POST" enctype="multipart/form-data"> <label>Bitte wählen sie eine Datei zum hochladen aus.</label> <input name="datei" type="file" value="" /> <br /> <input type="submit" value="Datei hochladen" /> </form> <?php if (!empty($_FILES)) { // horizontale Linie echo "<hr />"; echo "<h2>Folgende Datei wurde gesendet.</h2>"; echo "<pre>\r\n"; echo htmlspecialchars(print_r($_FILES)); echo "</pre>\r\n"; } ?> </body> </html> |
Nach dem Senden einer Datei wird folgendes angezeigt. Der Name des Input-Feldes wird uns als Name für das Array wiedergegeben, wir erfahren den Dateinamen [name], Dateityp [type], Dateigröße [size], Fehler [error] und dem temporären Dateinamen [tmp_name]. Den temporären Dateinamen benötigen wir zum Speichern der Datei auf unserem Webserver (Webspace). Hierzu legen wir auf dem Webserver im Verzeichnis der index.php ein neues Verzeichnis namens „uploads“ an.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
<html> <head> <meta charset="utf-8" /> <title>Upload einer Datei</title> </head> <body> <h1>Upload einer Datei</h1> <hr /> <form method="POST" enctype="multipart/form-data"> <label>Bitte wählen sie eine Datei zum hochladen aus.</label> <input name="datei" type="file" value="" /> <br /> <input type="submit" value="Datei hochladen" /> </form> <?php if (!empty($_FILES)) { // horizontale Linie echo "<hr />"; echo "<h2>Folgende Datei wurde gesendet.</h2>"; echo "<pre>\r\n"; echo htmlspecialchars(print_r($_FILES)); echo "</pre>\r\n"; $datei_ordner = "uploads/"; $datei_name = $datei_ordner . basename(urlencode($_FILES["datei"]["name"])); // Speichern des Bildes im Dateisystem if (move_uploaded_file($_FILES["datei"]["tmp_name"], $datei_name)) { echo "Datei wurde erfolgreich hochgeladen."; } else { echo "Fehler beim Hochladen der Datei."; } // Direkte Anzeige eines Bildes if(@is_array(getimagesize($datei_name))){ echo "<img src=".$datei_name ." width=\"400\" />"; } } ?> </body> </html> |
Den Quelltext unseres PHP Upload-Scripts erweitern wir ebenfalls um wenige Zeilen, so dass die Datei gespeichert wird (und Bilder direkt angezeigt werden). Wichtig ist die interne PHP Funktion move_uploaded_file(temporäre Dateiname, neuer Dateiname) , hier passiert die ganze Magie des Speicherns auf dem Webspace. Auf dem Webserver wird die hochgeladene temporäre Datei durch die PHP Funktion verschoben und gespeichert. Die hochgeladenen Dateien werden nun im Verzeichnis „uploads“ abgelegt und verfügbar gemacht. Zusehen ist die hochgeladene Datei auf dem Webserver.
Upload von Dateien (mehreren Dateien)
Das Hochladen von mehreren Dateien gleichzeitig gestaltet sich im Anschluss nicht mehr schwer. Dennoch müssen wir den Quellcode an verschiedenen Stellen ändern.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<html> <head> <meta charset="utf-8" /> <title>Upload einer Datei</title> </head> <body> <h1>Upload einer Datei</h1> <hr /> <form method="POST" enctype="multipart/form-data"> <label>Bitte wählen sie Dateien (STRG Taste zum markieren) zum hochladen aus.</label> <input name="datei[]" type="file" value="" multiple /> <br /> <input type="submit" value="Datei hochladen" /> </form> <?php if (!empty($_FILES)) { // horizontale Linie echo "<hr />"; echo "<h2>Folgende Dateien wurden gesendet.</h2>"; echo "<pre>" . var_dump($_FILES) . "</pre>"; $datei_ordner = "uploads/"; $datei_anzahl = count($_FILES['datei']['name']); echo "Anzahl der Dateien $datei_anzahl"; // FOR Schleife zum Speichern der Dateien for ($i = 0; $i < $datei_anzahl; $i++) { $datei_name = $datei_ordner . basename(urlencode($_FILES["datei"]["name"][$i])); // Speichern des Bildes im Dateisystem if (move_uploaded_file($_FILES["datei"]["tmp_name"][$i], $datei_name)) { echo "Datei wurde erfolgreich hochgeladen."; } else { echo "Fehler beim Hochladen der Datei."; } // Direkte Anzeige eines Bildes if (@is_array(getimagesize($datei_name))) { echo "<br /><img src=" . $datei_name . " width=\"400\" />"; } } } ?> </body> </html> |
Die Zeile <input name="datei" type="file" value="" /> aus dem obigen Beispiel für eine einzelne Datei erweitern wir einfach zu <input name="datei[]" type="file" value="" multiple /> . $_FILES enthält jetzt ein Array mit den Dateien, welcher über eine FOR-Schleife angesprochen werden können. Testet es einfach selbst =).
Hochladen von nur zum Beispiel Bildern
Für ein Portal möchte man zum Beispiel das nur gewissen Datei-Typen wie Bilder hochgeladen werden dürfen. Dies kann man mit der Angabe von accept="image/*" oder accept=".png, .jpg, .jpeg" im Input-File-Tag erreichen, jedoch sollte auch im PHP Script eine Prüfung der Dateitypen (Dateiformate) erfolgen. Ich würde daher die zweite Variante empfehlen, so dass der Dateiname mit der PHP-Funktion in_array geprüft werden kann. Bitte studiert das folgenden Quellcode-Beispiel. Der Explorer bietet zum Hochladen durch accept=“*“ die folgenden Dateiendungen (Formate) an.
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
<html> <head> <meta charset="utf-8" /> <title>Upload einer Datei</title> </head> <body> <h1>Upload einer Datei</h1> <hr /> <form method="POST" enctype="multipart/form-data"> <label>Bitte wählen sie Dateien (STRG Taste zum markieren) zum hochladen aus.</label> <input name="datei[]" type="file" value="" accept=".png, .jpg, .jpeg" multiple /> <br /> <input type="submit" value="Datei hochladen" /> </form> <?php if (!empty($_FILES)) { // horizontale Linie echo "<hr />"; echo "<h2>Folgende Dateien wurden gesendet.</h2>"; echo "<pre>" . var_dump($_FILES) . "</pre>"; $datei_ordner = "uploads/"; $datei_anzahl = count($_FILES['datei']['name']); echo "Anzahl der Dateien $datei_anzahl.<br />"; $datei_erlaubt = ['jpg', 'jpeg', 'png']; // FOR Schleife zum Speichern der Dateien for ($i = 0; $i < $datei_anzahl; $i++) { $datei_endung = pathinfo($_FILES["datei"]["name"][$i], PATHINFO_EXTENSION); // Prüfung ob die Datei hochgeladen werden kann. if (in_array($datei_endung, $datei_erlaubt)) { $datei_name = $datei_ordner . basename(urlencode($_FILES["datei"]["name"][$i])); // Speichern des Bildes im Dateisystem if (move_uploaded_file($_FILES["datei"]["tmp_name"][$i], $datei_name)) { echo "Datei wurde erfolgreich hochgeladen.<br />"; } else { echo "Fehler beim Hochladen der Datei."; } // Direkte Anzeige eines Bildes if (@is_array(getimagesize($datei_name))) { echo "<br /><img src=" . $datei_name . " width=\"400\" />"; } } else { // Ausgabe der Fehlermeldung, falsch die Datei nicht hochgeladen werden darf. echo "Die Datei " . $_FILES['datei']['name'][$i] . " darf nicht hochgeladen werden.<br />"; } } } ?> </body> </html> |
Eine Prüfung des Dateiformats (*.jpg, *.png, *.gif) ist nötig, da nicht alle Browser die Auswahl von bestimmten Dateien implementiert haben oder unterstützen. Weiterhin versuchen Hacker auf anderen Wegen, Viren einzuschleusen. Zum Testen des Dateinamenfilters (Dateiendungen) lasst ihr die Angabe von accept=“*“ im Input-Tag einfach weg.
PHP Upload Einstellungen (bekannte Fehler)
Gerade beim Lernen einer Programmiersprache steckt der Fehlerteufel oft im Detail, so bei PHP auch. Es hilft positiv zu bleiben, wir haben alle mal klein angefangen und habe mit der Zeit das Wissen erworben. Gerade bei dem Hochladen von Dateien, Dokumenten und Bilder ist daran zu denken, das die Dateigröße vom Server angenommen wird und verarbeitet werden kann. Mir der in PHP eingebauten Funktion phpinfo(); kann man sich Konfigurationsdetails des Servers anschauen. Im Folgenden möchte ich mit euch im Bezug des PHP Uploads genauer darauf eingehen.
Direkte Einstellungen für Dateien (Files) in der php.ini
file_uploads=On Erlaubt dem Server das Annehmen der gesendeten Dateien. upload_tmp_dir="C:\xampp\tmp" Die Hochgeladenen Dateien werden hier zwischen gespeichert und können mit der Funktion move_uploaded_file($tmp_datei_name, $neuer_datei_name) in einem Verzeichnis des Webspaces (Webhost) gespeichert werden. upload_max_filesize=40M Gibt gesamte Dateigröße an, für alle Dateien welche gemeinsam hochgeladen werden dürfen. max_file_uploads=20 Anzahl der Dateien welche gemeinsam mit einem Upload gemeinsam Hochgeladen werden dürfen.
Indirekte Einstellungen für Dateien (Files) in der php.ini
memory_limit=512M Gibt die maximale Script-Größe, welche durch den Server verarbeitet werden dürfen – hierzu zählen auch die hochzuladenden Dateien. max_execution_time=120 Maximale Ausführungszeit in Sekunden, gerade bei größeren PHP-Anwendungen wo zum Beispiel die Systeme eigenständige Updates durchführen sollte dieser Wert angemessen hoch sein.
Hinweise
Der verwendete PHP-Code sollte natürlich nicht in einer Produktivumgebung verwendet werden. In einer Produktivumgebung sollten die abgelegten Dateien durch „kryptische“ Dateinamen (z.B. Hashs) vor unerlaubten Downloads geschützt werden. Vor dem Speichern sollte geprüft werden, ob eine Datei auf dem Webserver bereits existiert, damit diese nicht überschrieben wird. Der Dateiname sollte UNIX konform sein, sodass es keine Probleme mit der URL gibt, hierzu kann z.B. die PHP-Funktion urlencode() verwendet werden.
Weitere Informationen (externe Links):
-
- Tutorial von SELFHTML: https://wiki.selfhtml.org/wiki/PHP/Tutorials/File_Upload
- Tutorial von w3schools.com: https://www.w3schools.com/php/php_file_upload.asp