PHP Maniac

Das PHP Blog für PHP-Profis und alle die es werden wollen

Datei-Uploads mit PHP – Hochladen leicht gemacht

6 Juli, 2009 (12:02) | Allgemein, Code-Schnipsel, Grundlagen, Sicherheit | Von: PHP Maniac

Nachdem ich in meinem letzten Beitrag erläutert habe, wie ihr Informationen per Email an eure Besucher versenden könnt, stelle ich heute einen Weg vor, wie Ihr Dateien von den Besuchern in Form von Datei Uploads erhalten könnt. PHP bietet hier, wie so oft, einige praktische Funktionen für den Datei-Upload an, die sehr einfach zu verwenden sind. Leider ist aber auch bei diesem Thema die Sicherheit ein wichtiger Aspekt, denn man erlaubt ja (mehr oder weniger) fremden Leuten Dateien auf den eigenen Webserver zu übertragen. Aber fangen wir erst einmal mit dem Datei-Upload an sich an.

Das Formular

Für den Upload von Dateien durch den Besucher ist zunächst ein spezielles HTML Formular notwendig, dass das Hochladen von Dateien unterstützt. Im Prinzip unterscheidet es sich nicht groß von anderen Formularen, die ihr sonst so benutzt, aber der Teufel steckt wie immer im Detail:

<form action="upload.php" method="post" enctype="multipart/form-data">
Datei hochladen: <input type="file" name="meine_datei">
<inpupt type="submit" value="Hochladen>
</form>

Der einzige Unterschied zu normalen Formularen ist hier der zusätzliche Parameter „enctype“, der dem Browser mitteilt, wie er die angehängten Daten für die Übertragung kodieren soll. Damit der Benutzer komfortabel eine Datei von seinem System auswählen kann, verwenden wir außerdem ein Input vom Typ „file“, der im Browser einen Dialog zum Auswählen der Datei zur Verfügung stellt.

Ein erster Datei-Upload

Nun brauchen wir noch etwas PHP Code um die Daten vom Formular zu verarbeiten und die Datei abzuspeichern. Hierfür existiert bei PHP die Funktion move_uploaded_file(), die zum einen Prüft ob es sich wirklich um eine hochgeladene Datei handelt und diese dann in einen Ordner unserer Wahl verschiebt. Da der Rückgabewert vom Typ bool ist, können wir den Aufruf direkt in eine if-Abfrage einbauen:

<?
$dir = getcwd().'/files';

if($_FILES['datei_upload']['size'] > 0)
{
	if(move_uploaded_file($_FILES['datei_upload']['tmp_name'], $dir.$_FILES['datei_upload']['name']))
	{
		echo "Der Upload der Datei war erfolgreich!";
	}
	else
	{
		echo "Irgendwas stimmt hier nicht, Upload nicht erfolgreich!";
	}
}
else
{
	?>
		<form action="upload.php" method="post" enctype="multipart/form-data">
		Datei hochladen: <input type="file" name="datei_upload">
		<inpupt type="submit" value="Hochladen>
		</form>
	<?
}
?>

Das Beispiel prüft also zunächst ob eine Datei größer 0 Byte übertragen wurde. Ist dies nicht der Fall wird unser Upload-Formular angezeigt. Andernfalls versucht das Skript die hochgeladene Datei in den Ordner „files“ zu verschieben. Hierzu muss dieser natürlich existieren und PHP muss Schreibrechte auf diesen besitzen (CHMOD 777). Hat alles geklappt findet ihr eure hochgeladene Datei nach dem Upload in diesem Verzeichnis.

Informationen über hochgeladene Dateien

PHP stellt uns zu jeder hochgeladenen Datei einige Informationen zur Verfügung, diese befinden sich im Array $_FILES. Über den Index wird hier die gewünschte Datei ausgewählt, da durchaus auch mehrere Dateien gleichzeitig hochgeladen werden können. Den Namen der Datei im Array legt man über den Namen des File-Input-Elements im Formular fest und in unserem Fall ist das „datei_upload“.
Hier eine kleine Übersicht über die verfügbaren Informationen zu den hochgeladenen Dateien im $_FILES Array:

$_FILES['datei_upload']['name']		Ursprünglicher Dateiname auf dem Rechner des Benutzers
$_FILES['datei_upload']['type']		Mime-Type der Datei, wenn der Browser ihn zur Verfügung stellt
$_FILES['datei_upload']['size']		Dateigröße in Bytes
$_FILES['datei_upload']['tmp_name']	Temporärer Dateiname zum Zugriff auf die Datei nach dem Upload
$_FILES['datei_upload']['error']	Fehlercode, wenn beim Upload ein Problem auftritt

Wichtig hierbei ist, dass der Mime-Type vom Browser des Clients übertragen wird. Das ist ja eigentlich sehr praktisch, aber leider übertragen wieder nicht alle Browser diese Information oder sie könnte vom Besucher absichtlich manipuliert worden sein. Daher sollte man sich nicht auf den Mime-Type im $_FILES Array verlassen. Für die Verarbeitung von Bildern empfiehlt es sich vielmehr die Funktion GetImageSize() zu verwenden, die unter Anderem auch den Mime-Type der Datei bestimmt.

Datei-Upload mit Einschränkungen

In der Praxis wollen wir aber sicherlich nicht jede beliebige Datei akzeptieren und müssen daher einige zusätzliche Einschränkungen implementieren, die aus den hochgeladenen Dateien diejenigen auswählen, die unseren Kriterien entsprechen. Das folgende Beispiel zeigt einige der Möglichkeiten, die häufig benötigt werden:

$dir = getcwd().'/files/';

if($_FILES['datei_upload']['size'] > 0)
{
	if($_FILES['datei_upload']['size'] < 100000)
	{
		$info = GetImageSize($_FILES['datei_upload']['tmp_name']);
		
		if($info[2] != 0)
		{
			if($info[0] == 100 && $info[1] == 150)
			{
				if(move_uploaded_file($_FILES['datei_upload']['tmp_name'], $dir.$_FILES['datei_upload']['name']))
				{
					echo "Der Upload der Datei war erfolgreich!";
				}
				else
				{
					echo "Irgendwas stimmt hier nicht, Upload nicht erfolgreich!";
				}
			}
			else
			{
				echo "Bitte laden Sie nur Bilder mit einer Größe von 100x150 Pixeln hoch!";
			}
		}
		else
		{
			echo "Bitte laden Sie nur Bilder vom Typ .gif .jpg oder .png hoch!";
		}
	}
	else
	{
		echo "Die Maximalgröße für Uploads liegt bei 100kB";
	}
}
else
{
	?>
		<form action="upload.php" method="post" enctype="multipart/form-data">
		Datei hochladen: <input type="file" name="datei_upload">
		<inpupt type="submit" value="Hochladen>
		</form>
	<?
}

Die Funktion GetImageSize() liefert uns einen Array mit der Breite (Index 0), Höhe (Index 1) und dem Mime-Type (Index 2) des Bildes. Ist der Mime-Type gleich Null, so handelt es sich um kein (bekanntes) Bildformat (1 – GIF, 2 – JPG, 3 – PNG). Über den Array können wir so einschränken welche Bildgröße und Bildtypen erlaubt sind. Weiterhin prüfen wir mit dem $_FILES Array ob die Dateigröße unter 100kByte liegt. Ist einer der Werte nicht innerhalb unserer Vorgaben, so wird eine einfache Fehlermeldung ausgegeben.

Sicherheitsaspekte

Wie immer noch einige Worte zur Sicherheit: Bitte seid euch immer bewusst, dass ihr im Zweifelsfall fremden Leuten gestattet Dateien auf eurem Webserver abzulegen. Wenn möglich sollte kein direkter Zugriff auf den Upload-Ordner vom Internet aus bestehen oder dieser mit einem htaccess Passwort geschützt werden. Gelingt es einem Angreifer eine PHP Datei hochzuladen und über den Browser auf diese zuzugreifen, so hat er kompletten Zugriff auf euren Webspace. Daher immer alle Dateien sehr genau prüfen und am besten keinen direkten Zugriff auf hochgeladene Daten ermöglichen. Ist ein Zugriff zwangsläufig notwendig, so bietet es sich an den Zugriff selbst auch wieder über ein PHP-Skript zu gewährleisten, dass zusätzliche Sicherheit bietet. Eventuell schreibe ich hierzu in Zukunft auch nochmal einen Artikel.

Bis dahin viel Spaß mit den Dateiuploads!

Be Sociable, Share!

Kommentare

Kommentar von VLC-Player
Datum 30. Juli 2009 um 12:56 Uhr

Schöner Artikel!

Schreibe einen Kommentar