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
Beträge und Zahlen in PHP formatieren – number_format, sprintf und Intl
1234.5 ist keine Anzeige, sondern ein Wert. Auf der Rechnung soll 1.234,50 € stehen, in der API 1234.50 und im Dateinamen 1234-50. Drei Aufgaben, drei Werkzeuge – und ein Fehler, den fast jeder einmal macht.
Benannte Argumente in PHP 8 – Schluss mit true, false, null, true
Ein Aufruf wie erstelle($a, true, false, null, true) sagt nichts darüber, was die Wahrheitswerte bedeuten. Mit benannten Argumenten steht es im Aufruf – und optionale Parameter lassen sich überspringen.
Reguläre Ausdrücke in PHP – benannte Gruppen statt $m[3]
Ein Treffer-Array aus Zahlen liest sich nach zwei Wochen wie eine Geheimschrift. Benannte Gruppen geben jedem Teil einen Namen – und preg_replace_callback ersetzt damit Dinge, die kein einfacher Ersetzungsstring kann.