Hoofdstuk 19. Bestanden uploaden naar server

Inhoudsopgave
Met de POST methode uploaden
Standaard valkuilen
Meerdere bestanden uploaden
PUT methode ondersteuning

Met de POST methode uploaden

PHP kan 'file uploads' ontvangen van elke browser welke de RFC-1867 standaard volgt (Zoals Netscape Navigator 3+ en Microsoft Internet Explorer 3 met een patch van Microsoft, of ouder zonder patch). Dit maakt het mogelijk voor mensen om text en binary bestanden te uploaden. Met PHP's authenticatie en bestandsfuncties heb je volledige controle over wie waar wat mag uploaden en wat er met het bestand gebeurd zo gauw het geupload is.

PHP ondersteunt ook de PUT-methode voor bestand uploads. Dit wordt onder andere gebruikt door Netscape Composer en programma's die W3C's Amaya gebruiken. Zie PUT Methode Ondersteuning voor meer details.

Een 'bestands upload' scherm kan gemaakt worden met een speciaal form dat er zo uit ziet:

Voorbeeld 19-1. Bestand Upload Form


<FORM ENCTYPE="multipart/form-data" ACTION="_URL_" METHOD=POST>
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="1000">
Send this file: <INPUT NAME="userfile" TYPE="file">
<INPUT TYPE="submit" VALUE="Stuur Bestand">
</FORM>
     
De URL moet naar een PHP bestand wijzen. Het MAX_FILE_SIZE 'hidden' veld moet VOOR het 'file input' veld komen en de waarde hiervan wordt gebruikt als de maximaal toegestane grootte van het bestand dat geupload wordt. Deze waarde is in bytes.

In PHP 3 worden de volgende variablen gevuld in het script zodra de upload succesvol is afgerond. (aangenomen wordt dat register_globals aan is gezet in php3.ini). Als track_vars aanstaat zijn ze (ook) te vinden in de globale array $HTTP_POST_VARS. Let op: De variablen in het volgende voorbeeld hebben de prefix 'userfile' zoals aangegeven is in het bovenstaande voorbeeld:

Let op: het deel "$userfile" van de bovenstaande variablen is wat het NAME= veld van het INPUT veld met TYPE=file is. In het bovenstaande voorbeeld kozen we ervoor om het "userfile" te noemen.

PHP 4 gedraagt zich enigzins anders, in PHP4 word de globale array $HTTP_POST_FILES aangemaakt waarin informatie over het ge-uploade bestand wordt opgeslagen. Deze is alleen te gebruiken als track_vars is aangezet. In alle versies na PHP 4.0.2 staat deze echter standaard aan.

De inhoud van $HTTP_POST_FILES is als volgt: (Hier word weer gebruik gemaakt van "userfile" zoals in het bovenstaande voorbeeld.)

$HTTP_POST_FILES['userfile']['name']

De originele naam van het bestand op het systeem van de gebruiker.

$HTTP_POST_FILES['userfile']['type']

Het mime-type van het bestand als de browser deze informatie meegestuurd heeft. Bijvoorbeeld: "image/gif".

$HTTP_POST_FILES['userfile']['size']

De grootte van het ge-uploade bestand in bytes.

$HTTP_POST_FILES['userfile']['tmp_name']

De tijdelijke bestandsnaam waarin het ge-uploade bestand is opgeslagen op de server.

Ge-uploade bestanden worden standaard in de standaard tijdelijke directory van de server opgeslagen, tenzij er een andere locatie is opgegeven met het upload_tmp_dir directive in php.ini. De server zijn standaard tijdelijke kan worden veranderd worden door de 'environment' variable TMPDIR te veranderen in het 'environment' waar PHP in draait. Dit kun je niet doen in een script met de PHP functie putenv(). Deze 'environment' variable kan ook gebruikt worden om te controleren of bewerkingen op ge-uploade bestanden wel juist werken.

Voorbeeld 19-2. Validating file uploads

De volgende voorbeelden zijn voor PHP 3 versies boven 3.0.16 en voor PHP 4 versies boven 4.0.2. Kijk voor meer informatie bij de functies is_uploaded_file() en move_uploaded_file().


<?php 
if (is_uploaded_file($userfile)) {
    copy($userfile, "/plaats/voor/ge-uploadbestand");
} else {
    echo "Mogelijke file-upload aanval: bestandsnaam '$userfile'.";
}
/* ...of... */
move_uploaded_file($userfile, "/plaats/voor/ge-uploadbestand");
?>
     

Voor eerdere versies van PHP zal je iets als het volgende moeten gebruiken.

Opmerking: Dit zal niet werken in PHP 4 versies ouder dan 4.0.2. Dit voorbeeld is afhankelijk van een bepaalde functionaliteit in PHP welke veranderd is na deze versie.


<?php 
/* Gebruikerstest voor ge-upload bestand. */ 
function is_uploaded_file($filename) {
    if (!$tmp_file = get_cfg_var('upload_tmp_dir')) {
        $tmp_file = dirname(tempnam('', ''));
    }
    $tmp_file .= '/' . basename($filename);
    /* Gebruiker kan een slash als einde hebben in php.ini... */
    return (ereg_replace('/+', '/', $tmp_file) == $filename);
}

if (is_uploaded_file($userfile)) {
    copy($userfile, "/plaats/voor/ge-uploadbestand");
} else {
    echo "Mogelijke bestands-upload aanval: bestandsnaam '$userfile'.";
}
?>
     

Het PHP script welke het ge-uploade bestand ontvangt moet zelf implementeren wat er moet gebeuren met het ge-uploade bestand. Je kunt bijvoorbeeld besluiten om bestanden weg te gooien welke groter of juist kleiner zijn dan de $file_size variable. Je kunt de $file_type variable gebruiken om bestanden te verwijderen welke niet voldoen aan een bepaald criteria. Wat je ook doet, je moet het bestand uit de tijdelijke directory verwijderen of het verplaatsen naar een andere directory.

Het bestand zal worden verwijderd uit de tijdelijke directory aan het einde van het script als het bestand niet verplaatst of hernoemd is.