W3docs

PHP Datei-Upload

Lernen Sie, wie Sie in PHP Datei-Uploads sicher implementieren – mit $_FILES, move_uploaded_file() und wichtigen Validierungsschritten.

Datei-Uploads sind eine häufige Anforderung in der Webentwicklung. Ob Profilbild, PDF-Dokument oder CSV-Import – Benutzern das Senden von Dateien an Ihren Server zu ermöglichen, ist eine Kernfunktion der meisten Anwendungen. In PHP wird dies durch die Funktion move_uploaded_file() zusammen mit dem superglobalen Array $_FILES realisiert.

Dieses Kapitel behandelt den gesamten Upload-Ablauf: die Konfiguration des HTML-Formulars, das Lesen der Metadaten der hochgeladenen Datei aus $_FILES, deren sichere Validierung und das Verschieben an den endgültigen Speicherort. Außerdem werden die Upload-Fehlercodes und die PHP-Konfigurationseinstellungen erläutert, die Upload-Limits steuern.

Wie ein PHP-Datei-Upload funktioniert

Ein Datei-Upload läuft in drei Phasen ab:

  1. Der Browser sendet die Datei in einer multipart/form-data-POST-Anfrage.
  2. PHP empfängt die Datei und schreibt sie an einen temporären Speicherort auf der Festplatte und stellt dann Details dazu im Array $_FILES bereit.
  3. Ihr Skript validiert die Datei und verschiebt sie mit move_uploaded_file() vom temporären an einen dauerhaften Speicherort.

Die temporäre Datei wird am Ende der Anfrage automatisch gelöscht, wenn Sie sie nicht verschieben. Sie müssen sie daher während derselben Anfrage verarbeiten.

Das superglobale Array $_FILES

Wenn eine Datei hochgeladen wird, werden die Informationen darüber im superglobalen Array $_FILES gespeichert. Für ein Formularfeld mit dem Namen userfile enthält das Array folgende Schlüssel:

  • $_FILES['userfile']['name'] - Der ursprüngliche Name der hochgeladenen Datei.
  • $_FILES['userfile']['type'] - Der MIME-Typ der hochgeladenen Datei.
  • $_FILES['userfile']['size'] - Die Größe der hochgeladenen Datei in Bytes.
  • $_FILES['userfile']['tmp_name'] - Der temporäre Speicherort der hochgeladenen Datei auf dem Server.
  • $_FILES['userfile']['error'] - Ein Fehlercode, der angibt, ob beim Datei-Upload ein Problem aufgetreten ist (siehe die Fehlercodes unten).

Schritt 1: Das HTML-Formular

Das Attribut enctype des Formulars muss auf multipart/form-data gesetzt werden, und die Methode muss POST sein. Ohne multipart/form-data sendet der Browser nur den Dateinamen, nicht den Inhalt, und $_FILES ist leer.

<form action="upload.php" method="POST" enctype="multipart/form-data">
  <input type="file" name="userfile">
  <input type="submit" value="Upload">
</form>

Schritt 2: Den Upload validieren

Vertrauen Sie einer hochgeladenen Datei nie. Prüfen Sie vor dem Verschieben drei Dinge: dass der Upload selbst erfolgreich war, dass die Größe innerhalb Ihres Limits liegt und dass die Datei wirklich den erwarteten Typ hat.

Den Fehlercode prüfen

Überprüfen Sie immer zuerst $_FILES['userfile']['error']. PHP definiert benannte Konstanten für die möglichen Werte:

KonstanteWertBedeutung
UPLOAD_ERR_OK0Kein Fehler, die Datei wurde erfolgreich hochgeladen.
UPLOAD_ERR_INI_SIZE1Datei überschreitet upload_max_filesize in php.ini.
UPLOAD_ERR_FORM_SIZE2Datei überschreitet das Feld MAX_FILE_SIZE des Formulars.
UPLOAD_ERR_PARTIAL3Die Datei wurde nur teilweise hochgeladen.
UPLOAD_ERR_NO_FILE4Es wurde keine Datei hochgeladen.
UPLOAD_ERR_NO_TMP_DIR6Temporärer Ordner fehlt.
UPLOAD_ERR_CANT_WRITE7Datei konnte nicht auf die Festplatte geschrieben werden.

Typ und Größe sicher validieren

Verlassen Sie sich nicht auf $_FILES['userfile']['type']. Dieser Wert wird vom Browser geliefert und kann von einem Angreifer trivial gefälscht werden. Erkennen Sie stattdessen den echten MIME-Typ anhand des Dateiinhalts mit der finfo-Erweiterung und erzwingen Sie selbst ein Größenlimit:

$file = $_FILES['userfile'];

// 1. Did the upload succeed?
if ($file['error'] !== UPLOAD_ERR_OK) {
  exit("Upload failed with error code " . $file['error']);
}

// 2. Enforce a maximum size (2 MB here).
$maxBytes = 2 * 1024 * 1024;
if ($file['size'] > $maxBytes) {
  exit("File is too large.");
}

// 3. Detect the real MIME type, not the client-supplied one.
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime  = $finfo->file($file['tmp_name']);

$allowed = [
  'image/jpeg' => 'jpg',
  'image/png'  => 'png',
  'image/gif'  => 'gif',
];

if (!isset($allowed[$mime])) {
  exit("Only JPEG, PNG, and GIF images are allowed.");
}

Schritt 3: Die Datei an den endgültigen Speicherort verschieben

Sobald die Datei validiert ist, verschieben Sie sie mit move_uploaded_file(). Die Funktion nimmt zwei Argumente entgegen: den temporären Pfad ($_FILES['userfile']['tmp_name']) und den Zielpfad. Die Verwendung dieser Funktion anstelle von copy() oder rename() ist wichtig – sie verifiziert, dass die Datei ein echter HTTP-Upload war, was verhindert, dass ein Angreifer Ihr Skript dazu bringt, eine beliebige Serverdatei zu verschieben.

Generieren Sie den endgültigen Dateinamen selbst, anstatt dem ursprünglichen Namen zu vertrauen. Das vermeidet Directory-Traversal-Angriffe (ein Name wie ../../config.php) und das Überschreiben vorhandener Dateien:

$targetDir = "uploads/";

// Build a safe, unique file name; never trust the client's name.
$extension  = $allowed[$mime];
$safeName   = bin2hex(random_bytes(8)) . "." . $extension;
$targetFile = $targetDir . $safeName;

if (move_uploaded_file($file['tmp_name'], $targetFile)) {
  echo "The file was uploaded as " . $safeName;
} else {
  echo "There was an error saving the file.";
}

Weitere Details zu dieser Funktion und ihrer Begleitfunktion is_uploaded_file() finden Sie in den Referenzkapiteln move_uploaded_file() und is_uploaded_file().

Konfiguration, die Uploads beeinflusst

Einige php.ini-Direktiven begrenzen stillschweigend, was Ihr Skript empfangen kann. Wenn Uploads bei großen Dateien fehlschlagen, obwohl Ihr Code korrekt ist, überprüfen Sie Folgendes:

  • file_uploads — muss On sein, damit Uploads überhaupt funktionieren.
  • upload_max_filesize — die größte einzelne Datei, die PHP akzeptiert (Standard 2M).
  • post_max_size — der größte gesamte POST-Body; muss größer sein als upload_max_filesize.
  • max_file_uploads — die maximale Anzahl von Dateien in einer einzigen Anfrage.

Fazit

PHP-Datei-Uploads sind ein grundlegender Bestandteil der Webentwicklung. Mit dem superglobalen Array $_FILES und der Funktion move_uploaded_file() können Sie Uploads in nur wenigen Zeilen verwalten. Das Schwierige daran ist, es sicher zu tun: Überprüfen Sie immer den Upload-Fehlercode, erzwingen Sie ein Größenlimit, erkennen Sie den echten MIME-Typ mit finfo anstatt $_FILES[...]['type'] zu vertrauen, und generieren Sie Ihren eigenen Dateinamen, damit der Client nie kontrollieren kann, wo die Datei landet. Zur Verarbeitung der gespeicherten Datei im Anschluss lesen Sie PHP-Dateiverarbeitung und Formularvalidierung.

Übungen

Übung
Welche der folgenden Aussagen zu Datei-Uploads in PHP sind korrekt?
Welche der folgenden Aussagen zu Datei-Uploads in PHP sind korrekt?
Was this page helpful?