Datei-Uploads in PHP sicher entgegennehmen
Ein Upload-Formular ist schnell gebaut – aber ohne Prüfung ein Einfallstor. Ich zeige dir, wie du Uploads richtig annimmst: echten MIME-Typ prüfen, Größe begrenzen, einen zufälligen Namen vergeben und außerhalb des Web-Roots speichern.
Datei-Uploads sind eine der häufigsten Sicherheitslücken in PHP-Projekten. Das Gefährliche: Verlässt du dich auf den Dateinamen oder den vom Browser gemeldeten Typ, kann jemand ein PHP-Skript als „Bild" hochladen. Deshalb prüfe ich immer serverseitig.
Der sichere Ablauf
<?php
declare(strict_types=1);
$file = $_FILES['bild'] ?? null;
if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
exit('Kein gültiger Upload.');
}
// 1) Größe begrenzen (hier 5 MB)
if ($file['size'] > 5 * 1024 * 1024) {
exit('Datei zu groß.');
}
// 2) ECHTEN Typ am Inhalt prüfen – nicht dem Browser glauben
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($file['tmp_name']);
$erlaubt = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp'];
if (!isset($erlaubt[$mime])) {
exit('Nur JPEG, PNG oder WebP erlaubt.');
}
// 3) Eigenen, zufälligen Namen vergeben (nie den Original-Namen benutzen)
$name = bin2hex(random_bytes(16)) . '.' . $erlaubt[$mime];
// 4) Außerhalb des Web-Roots speichern
$ziel = __DIR__ . '/../uploads/' . $name;
if (!move_uploaded_file($file['tmp_name'], $ziel)) {
exit('Speichern fehlgeschlagen.');
}Warum jeder Schritt zählt
finfoliest den echten MIME-Typ aus dem Dateiinhalt.$file['type']kommt vom Browser und ist fälschbar.- Zufälliger Name verhindert, dass jemand über
../aus dem Ordner ausbricht oder eine bestehende Datei überschreibt. Er entfernt außerdem eine gefährliche.php-Endung. - Außerhalb des Web-Roots heißt: Der Server führt eine hochgeladene Datei niemals als Skript aus. Zum Ausliefern nimmst du dann ein PHP-Skript mit
readfile().
Willst du auf Nummer sicher gehen, kodierst du Bilder nach dem Upload neu (z. B. mit der GD-Bibliothek) – das strippt versteckte Inhalte und EXIF-Daten gleich mit.
Genau so nehme ich Kunden-Uploads in meinen Projekten an. Brauchst du das sauber gebaut? Melde dich über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
array_find, array_any und array_all in PHP 8.4 – Arrays durchsuchen ohne Schleife
„Gibt es einen inaktiven Eintrag?", „Sind alle bezahlt?", „Hol mir den ersten Treffer" – dafür hast du bisher eine foreach-Schleife mit break geschrieben. PHP 8.4 macht daraus je eine Zeile, die genau sagt, was sie meint.
First-Class-Callable-Syntax in PHP: aus strlen(...) wird ein echter Wert
Funktionen als Zeichenketten weiterzureichen – 'strlen', [$objekt, 'methode'] – hat nie jemand gemocht: kein Tippfehlerschutz, keine Sprungmarke in der IDE. Seit PHP 8.1 schreibst du drei Punkte und bekommst ein Closure-Objekt.
Dateirechte verstehen – was 755 und 644 wirklich bedeuten
chmod 777 löst jedes Rechteproblem – und schafft ein größeres. Die drei Ziffern sind kein Zauberspruch, sondern eine simple Addition. Wer sie einmal verstanden hat, rät nie wieder.