upload

Mit PHP kann man Dateien auf den Server laden. Die Auswahl erfolgt über ein Formular. Vor dem eigentlichen Hochladen, sollte die Datei auf Größe und Dateiendung überprüft werden. Eine hochgeladene Datei wird erst in ein temporäres Verzeichnis mit einem temporären Namen geladen und wird erst auf copy() Befehl in das gewünschte Verzeichnis kopiert.

Sicherheit ist hierbei in wichtiges Thema. Siehe dazu auch weiterführende Informationen bei Wiki PHP Upload.

$_FILES

In folgendem Beispiel wird ein Formular für die Dateiauswahl erstellt. Die Datei wird allerdings noch nicht abgespeichert. Das action Attribut verweist auf die eigene PHP Seite. Man könnte das action Attribut auch weglassen. Die weiteren Attribute sind Pflicht: method="post" enctype="multipart/form-data"

Das input Feld hat das Attribut type="file". Durch die Angabe des Mime Types im accept Attribut überprüft der Browser, ob der richtige Datentyp ausgwählt wurde. Das input type="file" zeigt einen Auswahlbutton an, der die Möglichkeit bietet aus dem Dateisystem eine Datei auszuwählen. Nach Abschicken des Formulars, kann man über das superglobalen Array $_FILES[] Informationen über die Datei abrufen. siehe unten
Die Datei wird temporär abgelegt und muss dann noch gespeichert werden. $_FILES["datei"]["tmp_name"].

siehe Beispiel

<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post" enctype="multipart/form-data">
<p>Datei: <input name="datei" type="file" accept="image/png"></p>
<p><input type="submit" value="Senden"></p>
</form>

 <?php
      if (isset($_FILES["datei"])) {
              foreach ($_FILES["datei"] as $key => $val) {
                  echo "$key : $val <br> \n";
              }
      }
  ?>

Das Abspeichern der Datei sollte selbstverständlich erst dann stattfinden, wenn man einige Überprüfungen gemacht hat. Für dieses einfache Beispiel auf dem eigenen Rechner kann man folgende Zeilen anhängen, um ein PNG-Bild im gleichen Verzeichnis abzuspeichern:

        $temp = $_FILES["datei"]["tmp_name"];
        move_uploaded_file($temp, "bild.png");

Auswählen und hochladen

Im folgendem Beispiel gibt es 2 Seiten:

  1. upload.html : eine Seite mit einem Formular für die Dateiauswahl
  2. upload.php : das PHP Programm zur Überprüfung und den Upload.

Dateiauswahl per Formular

form

Für Dateiuploads braucht das Formular folgendes Enctype Attribut:
enctype="multipart/form-data"

input

type="file"

accept="image/gif,image/jpeg,image/png"

In dem optionalen accept Attribut kann man eine Anzahl von erlaubten Mime Types angeben. Es ist auch möglich Sternchen einzusetzen. accept="image/*" um beispielsweise alle Bildformate zu erlauben. In der PHP Datei sollte der Dateityp dennoch überprüft werden.

Das input Feld zeigt sich als "Datei Auswählen" Button Sobald der User eine Datei ausgewählt hat, erscheint der Name hinter dem Auswahlbutton und man kann auf Senden klicken.

HTML Formular

<form enctype="multipart/form-data" method="post">
<input type="file" name="datei" accept="image/gif,image/jpeg,image/png">
<input type="submit">
</form>

PHP

Über das superglobale Feld $_FILES kann man überprüfen, ob eine Datei hochgeladen wurde.

    if (!empty($_FILES) && $_FILES['datei']['error'] == UPLOAD_ERR_OK) {
        $type = mime_content_type($_FILES['datei']['tmp_name']);
    } else {
        echo "Irgendwas ist schief gelaufen. ";
        exit();
    }

Über das superglobale Feld $_FILES kann man mehrere Informationen zur Datei abrufen, wie Dateigröße, ursprünglicher Name, Dateityp. $_FILES erwartet den Namen welcher dem input Element zugewiesen wurde.

Dateiinformationen
$_FILES["datei"]["name"] ursprünglicher Name
$_FILES["datei"]["tmp_name"] temporärer Name
$_FILES["datei"]["size"] Dateigröße in Bytes
$_FILES["datei"]["type"] MIME Type
$_FILES["datei"]["error"] möglicher Fehlercode

Überprüfung

Datentyp / Mimetype

$type = $_FILES["datei"]["type"];

Der so ermittelte Mimetype stammt vom Browser und könnte fehlerhaft sein. Daher wird er mittels mime_content_type() ermittelt.

$type = mime_content_type($_FILES['datei']['tmp_name']);

Ein assoziatives Array kann man mit isset überprüfen. In diesem Fall ein Array mit erlaubten Mime Types. Außerdem kann man nach Überprüfung die Endung abspeichern, die man für der Erstellung eines neuen Namens später gebrauchen kann.

    $allowed_files = [
        'image/jpeg' => 'jpg',
        'image/gif' => 'gif',
        'image/png' => 'png'
        'image/webp' => 'webp'
    ];
if(isset($allowed_files[$type])){
  $endung = $allowed_files[$type];
  }else{
  echo "Der Dateityp ist nicht erlaubt.";
  exit();
  }
  

Dateigröße

 $size = $_FILES["datei"]["size"];

Das superglobale Feld $_FILES liefert die Dateigröße in bytes. Diese kann man mit einer definierten maximal Größe überprüfen.

$maxsize = 1024 * 1024;

Entspricht 1000 kb oder einem 1Mb

if($size > $maxsize){
  echo "Die Dateigröße ist zu hoch.";
  exit();
  }

Datei speichern mit copy()

Schlußendlich wird die Datei endgütlig in das gewünscht Verzeichnis hochgeladen mit der Methode copy() welche 2 Parameter hat, die Datei und der neue Dateipfad und Name. Alternativ könnte man auch den ursprünglichen Namen der Datei nehmen.

    $pfadName = "upload/bild." . $endung;
    copy($_FILES["datei"]["tmp_name"], $pfadName);
    echo "Die Datei wurde erfolgreich hochgeladen.";

Es folgt der gesamte Code

PHP

    if (!empty($_FILES) && $_FILES['datei']['error'] == UPLOAD_ERR_OK) {
        $type = mime_content_type($_FILES['datei']['tmp_name']);
    } else {
        echo "Irgendwas ist schief gelaufen. ";
        exit();
    }

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

    if (isset($allowed_files[$type])) {
        $endung = $allowed_files[$type];
    } else {
        echo "Dateityp nicht erlaubt";
        exit();
    }


    $maxsize = 1024 * 1024; // 1MB
    $size = $_FILES["datei"]["size"];

    echo "Dateigröße: " .  $size . " byte <br>";

    if ($size >= $maxsize) {
        echo "Die Datei ist zu groß";
        exit();
    }

    $pfadName = "upload/bild." . $endung;

    copy($_FILES["datei"]["tmp_name"], $pfadName);
    echo "Die Datei wurde erfolgreich hochgeladen";

Dateinamen erzeugen

Mehrere Dateien mit fortlaufender Nummer in ein Verzeichnis laden

Im obigen Beispiel wurde Pfad und Dateiname festgelegt und somit kann man nur eine Datei hochladen, weil eine weitere hochgeladene Datei, die vorige mit gleichem Namen überschreibt.

Es würde auch nichts nützen, den original Dateinamen zu verwenden, denn auch damit könnte eine Datei überschrieben werden. Vor allen Dingen wenn es darum geht, dass diese hochgeladenen Dateien im Netz angezeigt werden, kommt noch hinzu, dass die Dateinamen keine Leerzeichen oder Sonderzeichen und Umlaute enthalten sollten.

Daher werden hier Dateinamen mit fortlaufender Nummer erzeugt. Wenn man die Anzahl der Dateien im Upload-Verzeichnis ermittelt, kann man daraus einen neuen Dateinamen erzeugen und somit wird keine Datei überschrieben.

Im Beispiel wird auf einen Ordner namens upload zugegriffen, der im gleichen Verzeichnis wie das PHP-Programm liegt. scandir('./upload/')
Siehe dazu Dateien / Verzeichnisse

Mit scandir() wird ein Array erzeugt, welches alle Dateien enthält, sowie den eigenen Ordner und den übergeordneten Ordner. Somit ist die Anzahl der Dateien count($files) - 2;
Wenn noch keine Dateien vorhanden sind, sollte die Anfangszahl 1 lauten also count($files) -1;
Daraus wird dann eine fortlaufen Nummer erzeugt, die in dem Dateinamen integriert wird.

$files = scandir('./upload/');
$files_count = count($files) - 1; 
$name = "upload/img_" . $files_count . ".png";

Ersetze das vorige Beispiel um diese Programmierung und setze den $name bei der Methode copy() ein. Eventuell kommt noch eine ausgelesene Dateiendung hinzu.

copy($_FILES["datei"]["tmp_name"], $name);

 


Webdesign / PHP / mySQL / Dreamweaver MX Tipps
Copyright © Michael Albers
www.pastorpixel.de