Appearance
Kapitel 13: Datei-Upload und Bildverarbeitung
13.1 Datei-Upload-Formular
Grundlegende Upload-Formular-Struktur
html
<!-- upload_formular.html -->
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Datei-Upload</title>
</head>
<body>
<h2>Datei-Upload</h2>
<!-- Wichtig: enctype="multipart/form-data" muss gesetzt sein! -->
<form method="post" action="upload_verarbeiten.php" enctype="multipart/form-data">
<label>Datei auswählen:<br>
<input type="file" name="datei" required>
</label><br><br>
<label>Maximale Dateigröße: 5MB<br>
<input type="hidden" name="MAX_FILE_SIZE" value="5242880">
</label><br><br>
<button type="submit">Hochladen</button>
</form>
</body>
</html>Wichtige Hinweise:
method="post"muss verwendet werden (GET hat Limit)enctype="multipart/form-data"muss gesetzt sein (sonst funktioniert Upload nicht!)MAX_FILE_SIZE(optional) kann die Dateigröße vorab begrenzen
13.2 $_FILES verwenden (Upload-Informationen erhalten)
Die $_FILES Superglobal-Variable
Wenn eine Datei hochgeladen wird, stehen die Informationen in $_FILES zur Verfügung.
php
<?php
// upload_verarbeiten.php
echo "<pre>";
print_r($_FILES);
echo "</pre>";
/*
Ausgabe-Beispiel:
Array
(
[datei] => Array
(
[name] => meins_bild.jpg // Originaldateiname
[type] => image/jpeg // MIME-Typ
[tmp_name] => C:\xampp\tmp\php123.tmp // Temporärer Pfad
[error] => 0 // Fehlercode (0 = kein Fehler)
[size] => 204800 // Dateigröße in Bytes
)
)
*/
?>$_FILES Felder erklärt
| Feld | Beschreibung |
|---|---|
name | Originaldateiname (wie auf dem Computer des Benutzers) |
type | MIME-Typ der Datei (z.B. image/jpeg, application/pdf) |
tmp_name | Temporärer Pfad, wohin PHP die Datei während des Uploads speichert |
error | Fehlercode (0 = kein Fehler, siehe unten) |
size | Dateigröße in Bytes |
Fehlercodes bei $_FILES
| Fehlercode | Konstante | Beschreibung |
|---|---|---|
| 0 | UPLOAD_ERR_OK | Kein Fehler, Upload erfolgreich |
| 1 | UPLOAD_ERR_INI_SIZE | Datei größer als upload_max_filesize in php.ini |
| 2 | UPLOAD_ERR_FORM_SIZE | Datei größer als MAX_FILE_SIZE im Formular |
| 3 | UPLOAD_ERR_PARTIAL | Datei nur teilweise hochgeladen |
| 4 | UPLOAD_ERR_NO_FILE | Keine Datei hochgeladen |
| 6 | UPLOAD_ERR_NO_TMP_DIR | Kein temporäres Verzeichnis |
| 7 | UPLOAD_ERR_CANT_WRITE | Fehler beim Schreiben auf Datenträger |
| 8 | UPLOAD_ERR_EXTENSION | Eine PHP-Erweiterung hat den Upload gestoppt |
13.3 Upload-Validierung (Größe, Typ, Umbenennen)
Upload-Validierung durchführen
php
<?php
// upload_verarbeiten.php
header('Content-Type: text/html; charset=utf-8');
// Prüfen, ob Datei hochgeladen wurde
if (!isset($_FILES['datei']) || $_FILES['datei']['error'] !== 0) {
die("Fehler beim Upload: " . uploadFehlerMeldung($_FILES['datei']['error']));
}
$datei = $_FILES['datei'];
// 1. Dateigröße prüfen (max. 5MB)
$max_groesse = 5 * 1024 * 1024; // 5MB in Bytes
if ($datei['size'] > $max_groesse) {
die("Datei ist zu groß! Maximale Größe: 5MB");
}
// 2. Dateityp prüfen (nur Bilder erlaubt)
$erlaubte_typen = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($datei['type'], $erlaubte_typen)) {
die("Nur JPG, PNG und GIF sind erlaubt!");
}
// 3. Dateiendung prüfen
$erlaubte_endungen = ['jpg', 'jpeg', 'png', 'gif'];
$dateiname = $datei['name'];
$dateiendung = strtolower(pathinfo($dateiname, PATHINFO_EXTENSION));
if (!in_array($dateiendung, $erlaubte_endungen)) {
die("Ungültige Dateiendung!");
}
// 4. Datei umbenennen (Sicherheit!)
$neuer_dateiname = uniqid() . '_' . time() . '.' . $dateiendung;
// 5. Zielverzeichnis prüfen/erstellen
$ziel_verzeichnis = 'uploads/';
if (!is_dir($ziel_verzeichnis)) {
mkdir($ziel_verzeichnis, 0755, true);
}
// 6. Datei verschieben (von temporärem Pfad zum Ziel)
$ziel_pfad = $ziel_verzeichnis . $neuer_dateiname;
if (move_uploaded_file($datei['tmp_name'], $ziel_pfad)) {
echo "Datei erfolgreich hochgeladen!<br>";
echo "Dateiname: " . htmlspecialchars($neuer_dateiname) . "<br>";
echo "Pfad: " . htmlspecialchars($ziel_pfad) . "<br>";
echo "<img src='" . $ziel_pfad . "' width='300'>";
} else {
echo "Fehler beim Verschieben der Datei!";
}
// Hilfsfunktion für Fehlermeldungen
function uploadFehlerMeldung($fehlercode) {
switch ($fehlercode) {
case UPLOAD_ERR_INI_SIZE:
return "Datei überschreitet upload_max_filesize in php.ini";
case UPLOAD_ERR_FORM_SIZE:
return "Datei überschreitet MAX_FILE_SIZE im Formular";
case UPLOAD_ERR_PARTIAL:
return "Datei nur teilweise hochgeladen";
case UPLOAD_ERR_NO_FILE:
return "Keine Datei hochgeladen";
case UPLOAD_ERR_NO_TMP_DIR:
return "Kein temporäres Verzeichnis";
case UPLOAD_ERR_CANT_WRITE:
return "Fehler beim Schreiben";
case UPLOAD_ERR_EXTENSION:
return "Upload durch PHP-Erweiterung gestoppt";
default:
return "Unbekannter Fehler";
}
}
?>Sicherheitsmaßnahmen beim Datei-Upload
- Dateinamen ändern (um Überschreibungen und Code-Ausführung zu verhindern)
- Dateityp prüfen (nicht nur auf Dateiendung vertrauen!)
- Dateigröße begrenzen (Speicherplatz schützen)
- Upload-Verzeichnis außerhalb des Webroots (wenn möglich)
.htaccessim Upload-Verzeichnis (um Ausführung von PHP-Dateien zu verhindern)
apache
# .htaccess im Upload-Verzeichnis
deny from all
<FilesMatch "\.(jpg|jpeg|png|gif)$">
allow from all
</FilesMatch>13.4 Profilbild-Upload
Praxisbeispiel: Profilbild-Upload
php
<?php
// profilbild_upload.php
session_start();
header('Content-Type: text/html; charset=utf-8');
// Benutzer muss eingeloggt sein (Session-Prüfung)
if (!isset($_SESSION['eingeloggt']) || $_SESSION['eingeloggt'] !== true) {
die("Bitte erst einloggen!");
}
$benutzer_id = $_SESSION['benutzer_id'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Upload-Validierung (wie in 13.3)
if (!isset($_FILES['profilbild']) || $_FILES['profilbild']['error'] !== 0) {
$fehler = "Bitte wählen Sie ein Bild aus.";
} else {
$datei = $_FILES['profilbild'];
// Größe prüfen (max. 2MB)
if ($datei['size'] > 2 * 1024 * 1024) {
$fehler = "Bild ist zu groß! Maximale Größe: 2MB";
}
// Typ prüfen
$erlaubte_typen = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($datei['type'], $erlaubte_typen)) {
$fehler = "Nur JPG, PNG und GIF sind erlaubt!";
}
// Endung prüfen
$dateiendung = strtolower(pathinfo($datei['name'], PATHINFO_EXTENSION));
$erlaubte_endungen = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($dateiendung, $erlaubte_endungen)) {
$fehler = "Ungültige Dateiendung!";
}
// Wenn keine Fehler: Upload durchführen
if (!isset($fehler)) {
// Altes Profilbild löschen (aus Datenbank abfragen)
// ...
// Neues Bild speichern
$neuer_dateiname = 'profil_' . $benutzer_id . '_' . time() . '.' . $dateiendung;
$ziel_pfad = 'uploads/profilbilder/' . $neuer_dateiname;
if (move_uploaded_file($datei['tmp_name'], $ziel_pfad)) {
// Dateipfad in Datenbank speichern
// $sql = "UPDATE benutzer SET profilbild = ? WHERE id = ?";
// ...
$erfolg = "Profilbild erfolgreich hochgeladen!";
} else {
$fehler = "Fehler beim Speichern der Datei!";
}
}
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Profilbild hochladen</title>
</head>
<body>
<h2>Profilbild hochladen</h2>
<?php if (isset($fehler)): ?>
<p style="color: red;"><?php echo $fehler; ?></p>
<?php endif; ?>
<?php if (isset($erfolg)): ?>
<p style="color: green;"><?php echo $erfolg; ?></p>
<?php endif; ?>
<form method="post" action="" enctype="multipart/form-data">
<label>Profilbild auswählen (max. 2MB):<br>
<input type="file" name="profilbild" accept="image/*" required>
</label><br><br>
<button type="submit">Hochladen</button>
</form>
<p><a href="profil.php">Zurück zum Profil</a></p>
</body>
</html>13.5 Bildbearbeitung (Thumbnail-Erstellung)
GD-Bibliothek verwenden
PHP hat eine eingebaute GD-Bibliothek für Bildbearbeitung.
php
<?php
// thumbnail_erstellen.php
// Funktion zum Erstellen eines Thumbnails
function erstelleThumbnail($quelldatei, $zieldatei, $max_breite = 200, $max_hoehe = 200) {
// 1. Bildinformationen abrufen
$bild_info = getimagesize($quelldatei);
$breite = $bild_info[0];
$hoehe = $bild_info[1];
$typ = $bild_info[2];
// 2. Quellbild laden (je nach Typ)
switch ($typ) {
case IMAGETYPE_JPEG:
$quelb_bild = imagecreatefromjpeg($quelldatei);
break;
case IMAGETYPE_PNG:
$quelb_bild = imagecreatefrompng($quelldatei);
break;
case IMAGETYPE_GIF:
$quelb_bild = imagecreatefromgif($quelldatei);
break;
default:
return false;
}
// 3. Neue Größe berechnen (Seitenverhältnis beibehalten)
$seitenverhaeltnis = $breite / $hoehe;
if ($breite > $hoehe) {
$neue_breite = $max_breite;
$neue_hoehe = $max_breite / $seitenverhaeltnis;
} else {
$neue_hoehe = $max_hoehe;
$neue_breite = $max_hoehe * $seitenverhaeltnis;
}
// 4. Neues (leeres) Bild erstellen
$neues_bild = imagecreatetruecolor($neue_breite, $neue_hoehe);
// 5. Transparenz für PNG/GIF beibehalten
if ($typ == IMAGETYPE_PNG || $typ == IMAGETYPE_GIF) {
imagecolortransparent($neues_bild, imagecolorallocatealpha($neues_bild, 0, 0, 0, 127));
imagealphablending($neues_bild, false);
imagesavealpha($neues_bild, true);
}
// 6. Bild skalieren (resizen)
imagecopyresampled(
$neues_bild, $quelb_bild,
0, 0, 0, 0,
$neue_breite, $neue_hoehe, $breite, $hoehe
);
// 7. Thumbnail speichern
switch ($typ) {
case IMAGETYPE_JPEG:
imagejpeg($neues_bild, $zieldatei, 90); // 90 = Qualität (0-100)
break;
case IMAGETYPE_PNG:
imagepng($neues_bild, $zieldatei);
break;
case IMAGETYPE_GIF:
imagegif($neues_bild, $zieldatei);
break;
}
// 8. Speicher freigeben
imagedestroy($quelb_bild);
imagedestroy($neues_bild);
return true;
}
// Beispielverwendung:
if (isset($_FILES['datei']) && $_FILES['datei']['error'] === 0) {
$quelldatei = $_FILES['datei']['tmp_name'];
$zieldatei = 'uploads/thumbnails/' . uniqid() . '.jpg';
if (erstelleThumbnail($quelldatei, $zieldatei, 200, 200)) {
echo "Thumbnail erfolgreich erstellt!<br>";
echo "<img src='" . $zieldatei . "'>";
} else {
echo "Fehler beim Erstellen des Thumbnails!";
}
}
?>Bildbearbeitung mit Imagick (Alternative zur GD-Bibliothek)
Imagick ist leistungsfähiger, aber nicht standardmäßig in PHP installiert.
php
<?php
// Erfordert: Imagick-Erweiterung installiert
function erstelleThumbnailImagick($quelldatei, $zieldatei, $max_breite = 200, $max_hoehe = 200) {
try {
// Bild laden
$bild = new Imagick($quelldatei);
// Seitenverhältnis beibehalten
$bild->thumbnailImage($max_breite, $max_hoehe, true);
// Thumbnail speichern
$bild->writeImage($zieldatei);
// Speicher freigeben
$bild->clear();
$bild->destroy();
return true;
} catch (Exception $e) {
return false;
}
}
?>Zusammenfassung
In diesem Kapitel haben Sie:
- ✅ Datei-Upload-Formulare erstellt (
enctype="multipart/form-data") - ✅
$_FILESSuperglobal-Variable verwendet (Upload-Informationen) - ✅ Upload-Validierung durchgeführt (Größe, Typ, Endung, Umbenennen)
- ✅ Profilbild-Upload implementiert
- ✅ Bildbearbeitung und Thumbnail-Erstellung gelernt (GD-Bibliothek)
Nächstes Kapitel: Wir werden Praxisprojekte erstellen (Gästebuch, Login-System, Warenkorb).
Übungsaufgaben:
- Erstellen Sie ein Upload-Formular für Bilder (mit Validierung)
- Implementieren Sie eine Profilbild-Upload-Funktion
- Erstellen Sie automatisch Thumbnails für hochgeladene Bilder
- Erstellen Sie eine Galerie, die alle hochgeladenen Bilder anzeigt
Häufige Fehler:
- ❌
enctype="multipart/form-data"vergessen → Upload funktioniert nicht! - ❌
$_FILESstatt$_POSTverwenden → Upload-Dateien sind in$_FILES! - ❌ Dateinamen nicht ändern → Sicherheitsrisiko (Code-Ausführung)!
- ❌
move_uploaded_file()vergessen → Datei bleibt im temporären Verzeichnis!
