Je ziet dit bericht omdat de EU dat een goed idee vindt. Deze website maakt gebruik van cookies van Google voor het tonen van advertenties en het bijhouden van bezoekersstatistieken. Google kan hiermee je surfgedrag volgen. Zie voor meer informatie het privacybeleid van Google. Via Your Online Choices kun tracking cookies van advertentiebedrijven blokkeren. Deze melding verbergen.

10 Bestanden Uploaden

Met behulp van PHP is het mogelijk om via een website bestanden te uploaden. Informatie over geupoade bestanden zijn beschikbaar in een speciaal soort formulier-variabele (zie ook hoofdstuk 8).

Theorie

De bestandsupload begint allemaal met een html-formulier met hierin een veld waarin een bestand van de harde schijf van de bezoeker kan worden geselecteerd. Het onderdeel waarmee de bezoeker het bestand kan uitkiezen wordt geleverd door de webbrowser.
Eenmaal verzonden pikt PHP informatie over het bestand op in de multi-dimensionale array $_FILES. De informatie in deze array wordt gebruikt om het bestand daadwerkelijk op de webserver op te slaan.

Formulier

Het begint dus allemaal met een HTML-formulier. Dit formulier dient minstens één input-veld van het type file te hebben. Uiteraard bevat het formulier ook een formulier-actie. Deze verwijst naar het PHP-script dat de verwerking van het formulier moet afhandelen. Het complete formulier kan er bijvoorbeeld als volgt uit zien:

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

Omdat het formulier gebruikt wordt om bestanden te uploaden, dient het attribuut enctype met als waarde multipart/form-data aan het formulier te worden meegegeven, zoals ook hierboven te zien is.

Bestandsinformatie in PHP

Gegevens van eventuele normale formuliervelden komen PHP binnen via $_POST. De gegevens van een bestandsveld komen echter binnen via $_FILES en bestaat voor ieder bestand uit meerdere onderdelen. $_FILES is dus een multidimensionale array en deze bevat de informatie zoals weergegeven in tabel 10.1.

Tabel 10.1: Opbouw van $_FILES
Sleutel Omschrijving
$_FILES['veldnaam']['name'] De oorspronkelijke bestandsnaam (inclusief extensie). Als we de bestandsextensie willen weten, dan moet deze dus nog van de bestandsnaam losgeweekt worden. Hierover later meer.
$_FILES['veldnaam']['type'] Het MIME-type van het bestand, bijvoorbeeld image/gif. Deze informatie wordt door de browser geleverd en is niet noodzakelijk correct. We doen hier verder niets mee.
$_FILES['veldnaam']['size'] De grootte van het bestand in bytes.
$_FILES['veldnaam']['tmp_name'] De tijdelijke naam van het bestand zoals het door PHP op de server is gezet. Deze naam is nodig om het bestand op z'n uiteindelijke plek te kunnen zetten.
$_FILES['veldnaam']['error'] Een error-code die betrekking heeft op de bestands-upload. Dit wordt nader bekeken in een voorbeeld met een uitgebreide controle op het geuploade bestand.

Bestandstype controleren

Zoals opgemerkt in tabel 10.1 is het MIME-type dat door de browser wordt aangereikt niet noodzakelijk betrouwbaar, omdat deze door de gebruiker vervalst kan worden. Om nu te bepalen of een geüpload bestand wel of niet op de server opgeslagen mag worden kan het MIME-type door PHP bepaald worden, of kan er naar de bestandsextensie gekeken worden.

Bij een 100% controle dient het MIME-type door PHP bepaald te worden (met behulp van finfo_file() (PHP >= 5.3.0) of mime_content_type() (PHP < 5.3.0)) en te worden vergeleken met de bestandsextensie van het bestand. Horen deze twee niet bij elkaar (bijvoorbeeld image/gif bij een .txt bestand), dan is er iets mis en dient het bestand geweigerd te worden.

Voor de veiligheid van de server is het echter voldoende om alleen naar de bestandsextensie te kijken. Immers, een bestand met een verkeerde extensie kan niet zomaar worden geopend of uitgevoerd zonder eerst de extensie terug te veranderen. Zo kan het geen kwaad als er een PHP-bestand met de extensie .txt wordt geüpload; immers dit bestand zal nooit door PHP worden uitgevoerd, omdat PHP geen txt-bestanden uitvoert. Om te controleren of een bestand nu wel of niet op de server mag worden opgeslagen zijn er nu dus nog twee opties: controleren of het bestand een extensie heeft die wel is toegestaan en het bestand opslaan, of controleren of het bestand een extensie heeft die niet is toegestaan en het bestand weigeren. De veilige weg is hier om een lijst te maken met extensies die wel zijn toegestaan, zodat een eventueel vergeten extensie geen problemen oplevert.

De array $_FILES levert niet direct de bestandsextensie, dus deze moet nog uit de bestandsnaam in $_FILES['bestand']['name'] gehaald worden. De bestandsextensie kan gedefinieerd worden als de tekens na de laatste punt in de bestandsnaam. Er is dus een gedeelte van de bestandsnaam nodig. Een gedeelte van een string kan worden geselecteerd met de functie substr():

string substr ( string $string , int $start [, int $length ] )

Deze functie geeft het gedeelte van $string, beginnend bij teken op positie $start. De tekens in de string worden geteld beginnend bij 0. De optionele parameter $length om de string af te kappen op een bepaalde lengte. Omdat nu het laatste deel van een string nodig is, kan $length worden weggelaten.

Omdat substr() vraagt om de positie van het eerste teken van de extensie, is het nodig om uit te vinden waar de laatste punt zich in de bestandsnaam bevindt. Dit kan met de functie strrpos():

int strrpos ( string $haystack , string $needle [, int $offset = 0 ] )

Deze functie geeft de positie (wederom tellend vanaf 0) van het laatste voorkomen van $needle (in dit geval de punt) in string $haystack (in dit geval de bestandsnaam). De eerste letter van de bestandsnaam bevindt zich dus één teken verder dan de positie van de laatste punt.

Verder kan het nog zo zijn dat de extensie van het geüploade bestand in hoofdletters is geschreven, in kleine letters, of iedere combinatie daarvan. Omdat PHP bij het vergelijken van twee strings verschil maakt tussen hoofdletters en kleine letters, is het handig om alles naar kleine letters om te zetten. Op die manier hoeven niet alle mogelijk combinaties (bij een extensie van drie letters zijn dat er al 2^3=6) gecontroleerd te worden. Het omzetten van een string naar kleine letters kan met de functie strtolower():

string strtolower ( string $str )

Deze drie functies kunnen worden samengesteld om de extensie van het bestand te achterhalen:

//vind locatie eerste letter extensie, door punt te zoeken en er 1 bij op te tellen
$pos = strrpos($_FILES['bestand']['name'], '.') + 1;
//vind extensie
$ext = substr($_FILES['bestand']['name'], $pos);
//converteer naar kleine letters
$ext = strtolower($ext);

Indien gewenst kan dit geheel ook worden samengevoegd tot één regel PHP code:

$ext = strtolower(substr($_FILES['bestand']['name'], strrpos($_FILES['bestand']['name'], '.') + 1));

Voor de daadwerkelijke controle is het handig om een array te maken met de toegestane extensies:

$ext_toegestaan = array('jpg', 'jpeg', 'png', 'gif');

Om te kijken of de extensie van het bestand in de array aanwezig is, kan gebruik worden gemaakt van de functie in_array():

bool in_array ( mixed $needle , array $haystack [, bool $strict ] )

Deze functie zoekt letterlijk naar een naald ($needle) in een hooiberg ($haystack). Als de naald bestaat, resulteert de functie in TRUE. Bestaat de naald niet, dan resulteert FALSE. In dit geval wordt de naald dus $ext en de hooiberg $ext_toegestaan:

$ext_toegestaan = array('jpg', 'jpeg', 'png', 'gif');
$ext = strtolower(substr($_FILES['bestand']['name'], strrpos($_FILES['bestand']['name'], '.') + 1));
if (in_array($ext, $ext_toegestaan)) {
    
//bestand is toegestaan
    
}
else {
    
//bestand is niet toegestaan
    
echo "Het bestandstype van het geuploade bestand is niet toegestaan.";
}

Bestandsgrootte controleren

De maximale toelaatbare bestandsgrootte hangt van vier factoren af:

Als gebruik wordt gemaakt van een webhost zijn de waarden in php.ini meestal niet zelf te wijzigen en dus een vast gegeven. Het heeft dan ook geen nut bestanden toe te staan groter dan de kleinste van deze drie waarden. De ingestelde grootte kan eenvoudig worden gecontroleerd via phpinfo() (zie hoofdstuk 1).

Als php.ini wel kan worden aangepast, dan is het goed om te weten dat UPLOAD_MAX_FILESIZE geldt per bestand (belangrijk in geval van meerdere uploads in één formulier), dat POST_MAX_SIZE geldt voor alle formulier-gegevens bij elkaar en dat MEMORY_LIMIT geldt voor het uitvoerende script. In geval van de standaardwaarden kunnen dus maximaal vier bestanden van maximaal 2 MB per stuk worden toegestaan per upload-actie.

Een zelf te kiezen maximum bestandsgrootte kan handig zijn om te voorkomen dat de server vol wordt gezet met hele grote bestanden. Als deze zelf gekozen waarde kleiner is dan UPLOAD_MAX_FILESIZE, dan wordt de maximale grootte niet automatisch beperkt door PHP en dient zelf een controle te worden uitgevoerd in het verwerkende script. Deze controle is eenvoudig, omdat de grootte van het geüploade bestand al door PHP wordt geleverd in $_FILES['bestand']['size'] en hoeft alleen nog maar vergeleken te worden met een zelf te kiezen maximumwaarde:

$max_grootte = 1*1024*1024;
if (
$_FILES['bestand']['size'] <= $max_grootte) {
    
//bestand is kleiner dan 1 MB

}
else {
    
//bestand is te groot
    
echo "Het geuploade bestand is te groot, de maximale bestandsgrootte is $max_grootte bytes.<br /><br />";
}

Bestand opslaan

Ieder geüpload bestand wordt eerst in een tijdelijke map geplaatst, waaruit het na het einde van het script automatisch wordt verwijderd. De controles voor bestandstype en bestandsgrootte kunnen op dit tijdelijke bestand worden uitgevoerd, maar om het bestand daadwerkelijk te bewaren moet het naar een definitieve plek worden verplaatst.

Het is handig om alle uploads in een aparte map bij elkaar te plaatsen. Omdat vanuit de meeste PHP-configuraties geen mappen kunnen worden aangemaakt, dient deze map handmatig aangemaakt te worden (bijvoorbeeld via FTP) en dient indien nodig voorzien te worden van de juiste rechten.

Het verplaatsen van het bestand gebeurt met de functie move_uploaded_file():

bool move_uploaded_file ( string $filename , string $destination )

Deze functie geeft TRUE als het verplaatsen is gelukt en FALSE als het bestand om wat voor reden dan ook (misschien bestaat de opgegeven map niet) mislukt. Als parameters dienen voor $filename de naam van het tijdelijke bestand te worden opgegeven (ofwel de waarde van $_FILES['bestand']['tmp_name']) en voor $destination de locatie (pad inclusief bestandsnaam) waar het bestand moet worden opgeslagen.

move_uploaded_file() controleert niet of een bestand al bestaat en zal een bestaand bestand dan ook overschrijven. In sommige situaties kan hier handig gebruik van worden gemaakt, in andere situaties zal eerst moeten worden gecontroleerd of er al een bestand met dezelfde naam bestaat om afhankelijk daarvan te besluiten de verplaatsingsactie wel of niet uit te voeren. Dit kan met de functie file_exists():

bool file_exists ( string $filename )

Deze functie is in hoofdstuk 7 al aan bod gekomen en geeft TRUE als het bestand gegeven door $filename op de lokale server bestaat en geeft FALSE als het bestand niet bestaat.

De twee functies kunnen samen worden gebruikt om eerst te kijken of er al een bestand met dezelfde naam bestaat en afhankelijk daarvan te bepalen of het bestand moet worden geaccepteerd of dat er een foutmelding moet worden gegeven:

$uploadmap = 'upload/';
if (!
file_exists($uploadmap.$_FILES['bestand']['name'])) {
    
//bestand bestaat nog niet
    
if (move_uploaded_file($_FILES['bestand']['tmp_name'], $uploadmap.$_FILES['bestand']['name'])) {
        
//bestand succesvol geupload
        
echo "Bestand succesvol geupload!";
    }
    else {
        
//upload mislukt
        
echo "Bestandsupload mislukt.";
    }
}
else {
    
//bestand bestaat
    
echo "Er bestaat al een bestand met dezelfde naam.";
}

Uploadfouten

In sommige gevallen mislukt een upload nog voordat het bestand door het script verwerkt kan worden. Wat er dan precies aan de hand is volgt uit de foutcode in $_FILES['bestand']['error']. De foutcodes die van belang kunnen zijn zijn weergegeven in tabel 10.2, voor de overige foutcodes wordt verwezen naar de PHP-handleiding.

Tabel 10.2: Foutcodes van bestand-uploads
Foutcode Waarde Omschrijving
UPLOAD_ERR_OK 0 Geen fout; het bestand is succesvol geüpload.
UPLOAD_ERR_INI_SIZE 1 Het bestand is groter dan UPLOAD_MAX_FILESIZE in php.ini.
UPLOAD_ERR_PARTIAL 3 Het bestand is niet volledig geüpload.
UPLOAD_ERR_NO_FILE 4 Er is geen bestand geüpload. Dit is in principe ook geen fout

De foutcode UPLOAD_ERR_NO_FILE kan worden gebruikt om te kijken of er daadwerkelijk een bestand is dat moet worden verwerkt. Als er geen bestand is, kan het hele verwerkingsgedeelte namelijk worden over geslagen:

//controleer of er een bestand is
if ($_FILES['bestand']['error'] === UPLOAD_ERR_NO_FILE) {
    
//er is geen bestand
    
echo "Er is geen bestand geselecteerd.";
}
else {
    
//er is wel een bestand
    //verwerk bestand
}

De overige foutcodes kunnen worden gebruikt om de gebruiker op de hoogte te stellen van eventuele problemen:

if ($_FILES['bestand']['error'] === UPLOAD_ERR_OK) {
    
//verwerk bestand
    
}
elseif (
$_FILES['bestand']['error'] === UPLOAD_ERR_INI_SIZE) {
    
//bestand te groot
    
echo "Het geuploade bestand is te groot, de maximale bestandsgrootte is $max_grootte bytes.";
}
elseif (
$_FILES['bestand']['error'] === UPLOAD_ERR_PARTIAL) {
    
//bestand niet volledig
    
echo "Het bestand is niet volledig geupload. Upload het bestand nogmaals.";
}
else {
    
//andere fout
    
echo "Er is een onbekende fout opgetreden. Probeer het later nogmaals.";
}

Praktijkvoorbeeld: Uploadscript

In dit praktijkvoorbeeld wordt de theorie uit dit hoofdstuk samengevat tot een werkend upload-formulier. Hierbij wordt uitgegaan van de volgende uitgangspunten:

Uploadscript

Het daadwerkelijke uploadscript is nu niets anders meer dan de code-voorbeelden uit de theorie in de juiste volgorde in elkaar te schuiven. Dit geeft het volledige uploadscript zoals hieronder weergegeven. We noemen het script upload.php en maken een submap met de naam upload aan in dezelfde map als waarin het script wordt geplaatst.

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Bestand Upload</title>
</head>
<body>
<h1>Bestand Upload</h1>

<?php
//toegestane grootte, toegestane bestandsextensies en uploadmap:
$max_grootte = 1.5*1024*1024;
$ext_toegestaan = array('jpg', 'png', 'txt');
$uploadmap = 'upload/';

if (!empty(
$_FILES)) {
    
//controleer of er een bestand is
    
if ($_FILES['bestand']['error'] === UPLOAD_ERR_NO_FILE) {
        
//er is geen bestand
        
echo 'Kies een bestand:';
    }
    else {
        
//er is een bestand
        
if ($_FILES['bestand']['error'] === UPLOAD_ERR_OK) {
            
//verwerk bestand
            //controleer grootte
            
if ($_FILES['bestand']['size'] <= $max_grootte) {
                
//bestand is kleiner dan toegestane grootte
                //vind locatie eerste letter extensie, door punt te zoeken en er 1 bij op te tellen
                
$ext = strtolower(substr($_FILES['bestand']['name'], strrpos($_FILES['bestand']['name'], '.') + 1));
                
//controleer of extensie toegestaan
                
if (in_array($ext, $ext_toegestaan)) {
                    
//bestand is toegestaan
                    //controleer of bestand al bestaat
                    
if (!file_exists($uploadmap.$_FILES['bestand']['name'])) {
                        
//bestand bestaat nog niet
                        
if (move_uploaded_file($_FILES['bestand']['tmp_name'], $uploadmap.$_FILES['bestand']['name'])) {
                            
//bestand succesvol geupload
                            
echo 'Bestand succesvol geupload!';
                        }
                        else {
                            
//upload mislukt
                            
echo 'Bestandsupload mislukt.';
                        }
                    }
                    else {
                        
//bestand bestaat
                        
echo 'Er bestaat al een bestand met dezelfde naam.';
                    }
                }
                else {
                    
//bestand is niet toegestaan
                    
echo 'Het bestandstype van het geuploade bestand is niet toegestaan.';
                }
            }
            else {
                
//bestand is te groot
                
echo 'Het geuploade bestand is te groot, de maximale bestandsgrootte is '.$max_grootte.' bytes.<br /><br />';
            }
        }
        elseif (
$_FILES['bestand']['error'] === UPLOAD_ERR_INI_SIZE) {
            
//bestand te groot
            
echo 'Het geuploade bestand is te groot, de maximale bestandsgrootte is '.$max_grootte.' bytes.';
        }
        elseif (
$_FILES['bestand']['error'] === UPLOAD_ERR_PARTIAL) {
            
//bestand niet volledig
            
echo 'Het bestand is niet volledig geupload. Upload het bestand nogmaals.';
        }
        else {
            
//andere fout
            
echo 'Er is een onbekende fout opgetreden. Probeer het later nogmaals.';
        }
    }
}
?>

<form method="post" enctype="multipart/form-data">
<input type="file" name="bestand"><br>
<input type="submit" value="Upload">
</form>

</body>
</html>

Opmerking: in het HTML formulier is dit keer geen attribuut action opgenomen. Dit betekent dat het formulier "naar zichzelf" verzonden wordt: de inhoud van het formulier wordt verzonden naar de pagina waarin het formulier is opgenomen. Hierdoor maakt het niet uit welke bestandsnaam het script heeft, als zoals in dit geval het formulier en het verwerkende PHP script in hetzelfde bestand zijn opgenomen.

Zelftest

  1. Wat is het juiste content-type (enctype) voor een upload-formulier?
    1. application/x-www-form-urlencoded
    2. multipart/form-data
    3. form/upload
    4. Het enctype mag worden weggelaten.
  2. Welke van de onderstaande stelling(en) is/zijn waar?
    I        Het MIME-type uit $_FILES['veldnaam']['type'] is betrouwbaar.
    II       De bestandsextensie kan door de gebruiker vervalst worden.
    1. Alleen stelling I is waar.
    2. Alleen stelling II is waar.
    3. Beide stellingen zijn waar.
    4. Beide stellingen zijn onwaar.
  3. Hoeveel bestanden kunnen er in één keer worden geüpload?
    1. 1
    2. 4
    3. Onbeperkt.
    4. Hangt af van de maximale bestandsgrootte en de configuratie van de server.
  4. Welke van onderstaande stelling(en) is/zijn waar?
    I        move_uploaded_file() controleert of een bestand al bestaat.
    II       Het is handig om UPLOAD_MAX_FILESIZE groter in te stellen dan POST_MAX_SIZE (in php.ini).
    1. Alleen stelling I is waar.
    2. Alleen stelling II is waar.
    3. Beide stellingen zijn waar.
    4. Beide stellingen zijn onwaar.
  5. Welke foutcode geeft aan dat een bestand te groot is?
    1. UPLOAD_ERR_OK
    2. UPLOAD_ERR_INI_SIZE
    3. UPLOAD_ERR_PARTIAL
    4. UPLOAD_ERR_NO_FILE
  6. De variabele $_SERVER['PHP_SELF']:
    1. geeft aan of er een bestand is geüpload.
    2. geeft de bestandsnaam van het huidige script.
    3. geeft aan of er fouten zijn in het huidige script.
    4. geeft de tijdelijke bestandsnaam van een geüpload bestand.

Antwoorden zelftest

Antwoorden

  1. b
  2. b
  3. d
  4. d
  5. b
  6. b

Oefening: Alternatieve Bestandsnaam

Ga uit van het uploadscript uit het Praktijkvoorbeeld. Voeg een extra tekstveld toe aan het formulier, waarin uploaders de mogelijkheid hebben een alternatieve bestandsnaam op te geven. Gebruik deze alternatieve bestandsnaam om het bestand op de server op te slaan. Controleer tevens of de extensie van de alternatieve bestandsnaam overeen komt met de extensie van het oorspronkelijke bestand. Plaats de oorspronkelijke extensie achter de alternatieve bestandsnaam als dat niet het geval is. Indien er geen alternatieve bestandsnaam wordt opgegeven, wordt de oorspronkelijke bestandsnaam gebruikt om het bestand op te slaan.

Uitwerking opdracht

Uitwerking

upload.php

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Bestand Upload</title>
</head>
<body>
<h1>Bestand Upload</h1>

<?php
//toegestane grootte, toegestane bestandsextensies en uploadmap:
$max_grootte = 1.5*1024*1024;
$ext_toegestaan = array('jpg', 'png', 'txt');
$uploadmap = 'upload/';

if (!empty(
$_FILES)) {
    
//controleer of er een bestand is
    
if ($_FILES['bestand']['error'] === UPLOAD_ERR_NO_FILE) {
        
//er is geen bestand
        
echo 'Kies een bestand:';
    }
    else {
        
//er is een bestand
        
if ($_FILES['bestand']['error'] === UPLOAD_ERR_OK) {
            
//verwerk bestand
            //controleer grootte
            
if ($_FILES['bestand']['size'] <= $max_grootte) {
                
//bestand is kleiner dan toegestane grootte
                //vind locatie eerste letter extensie, door punt te zoeken en er 1 bij op te tellen
                
$ext = strtolower(substr($_FILES['bestand']['name'], strrpos($_FILES['bestand']['name'], '.') + 1));
                
//controleer of extensie toegestaan
                
if (in_array($ext, $ext_toegestaan)) {
                    
//bestand is toegestaan, bepaal bestandsnaam
                    
if (empty($_POST['naam'])) {
                        
//geen nieuwe bestandsnaam gegeven, gebruik oorspronkelijke naam
                        
$bestandsnaam = $_FILES['bestand']['name'];
                    }
                    else {
                        
//bepaal extensie van nieuwe bestandsnaam
                        
$ext_alt = strtolower(substr($_POST['naam'], strrpos($_POST['naam'], '.') + 1));
                        if (
$ext == $ext_alt) {
                            
//extensie is gelijk aan origineel, naam is goed
                            
$bestandsnaam = $_POST['naam'];
                        }
                        else {
                            
//extensie is anders, plaats originele extensie achter gegeven naam
                            
$bestandsnaam = $_POST['naam'].'.'.$ext;
                        }
                    }
                    
//let op: in een productie omgeving moeten hier ook nog speciale tekens uit de bestandsnaam gehaald worden
                    //dit komt later terug in het hoofdstuk over reguliere expressies
                    
                    //controleer of bestand al bestaat
                    
if (!file_exists($uploadmap.$bestandsnaam)) {
                        
//bestand bestaat nog niet
                        
if (move_uploaded_file($_FILES['bestand']['tmp_name'], $uploadmap.$bestandsnaam)) {
                            
//bestand succesvol geupload
                            
echo 'Bestand succesvol geupload!';
                        }
                        else {
                            
//upload mislukt
                            
echo 'Bestandsupload mislukt.';
                        }
                    }
                    else {
                        
//bestand bestaat
                        
echo 'Er bestaat al een bestand met dezelfde naam.';
                    }
                }
                else {
                    
//bestand is niet toegestaan
                    
echo 'Het bestandstype van het geuploade bestand is niet toegestaan.';
                }
            }
            else {
                
//bestand is te groot
                
echo 'Het geuploade bestand is te groot, de maximale bestandsgrootte is '.$max_grootte.' bytes.<br /><br />';
            }
        }
        elseif (
$_FILES['bestand']['error'] === UPLOAD_ERR_INI_SIZE) {
            
//bestand te groot
            
echo 'Het geuploade bestand is te groot, de maximale bestandsgrootte is '.$max_grootte.' bytes.';
        }
        elseif (
$_FILES['bestand']['error'] === UPLOAD_ERR_PARTIAL) {
            
//bestand niet volledig
            
echo 'Het bestand is niet volledig geupload. Upload het bestand nogmaals.';
        }
        else {
            
//andere fout
            
echo 'Er is een onbekende fout opgetreden. Probeer het later nogmaals.';
        }
    }
}
?>

<form method="post" enctype="multipart/form-data">
Kies bestand: <input type="file" name="bestand"><br>
Wijzig bestandsnaam: <input type="text" name="naam"><br>
<input type="submit" value="Upload">
</form>

</body>
</html>