Uploaden

**
Noot: dit is geen compleet uploadscript. Hier staat alleen de informatie die je nodig hebt om een script op te zetten.
**

Om bestanden te uploaden heb je twee dingen nodig. Een formulier wat de bezoeker in staat stelt om een bestand te kiezen en door te sturen, en een PHP script dat het bestand opvangt en verwerkt.
Dat script moet een aantal zaken regelen die van extreem groot belang zijn om te voorkomen dat je gehackt wordt.

De HTML kant
Allereerst zul je een simpel formulier moeten maken waarin je aangeeft dat je graag wilt dat de gebruiker een bestand selecteert om te uploaden. Dit doe je met het file input element:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<form enctype="multipart/form-data" action="upload.php" method="post">
 <input type="file" name="naam_formveld_uploadfile"/><br />
 <input type="submit" value="Upload!"/>
</form>


Wanneer je nu op Upload! klikt zal de browser een POST-request in elkaar draaien (hoe dat er precies uit ziet zie je later). Het bestand komt uiteindelijk bij PHP aan en deze verwerkt de file vervolgens. Om met de file te kunnen werken zet PHP de geüploade file tijdelijk weg in een directory. Waar dit precies is wordt geregeld met de upload_tmp_dir configuratie optie in php.ini.

Belangrijk: Op het moment dat jouw script klaar is met uitvoeren wordt dit geüploade bestand verwijderd van de server. Kopieer je het bestand bijvoorbeeld niet naar een andere directory, dan ben je het dus kwijt.

De PHP kant
Server instellingen

PHP kent een aantal instellingen waarmee het uploaden van bestanden kan worden aan- en uitgezet, en waarmee kan worden bepaald hoe groot de bestanden mogen zijn, waar de tijdelijke bestanden worden bewaard etc. Je vindt deze instellingen in php.ini :

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
; Whether to allow HTTP file uploads.

; http://php.net/file-uploads

file_uploads = On

; Temporary directory for HTTP uploaded files (will use system default if not

; specified).

; http://php.net/upload-tmp-dir

upload_tmp_dir = "c:/tmp" ; <-- dit VOORBEELD komt van een lokale server!

; Maximum allowed size for uploaded files.

; http://php.net/upload-max-filesize

upload_max_filesize = 2M



De upload verwerken

Upload gelukt?

Kijken of het uploaden goed is gegaan:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
if ($_FILES['naam_formveld_uploadfile']['error']!=0)
{

    switch ($_FILES['naam_formveld_uploadfile']['error'])
    {
       case
UPLOAD_ERR_OK:
           break;
       case
UPLOAD_ERR_INI_SIZE:
           echo "The uploaded file exceeds the upload_max_filesize directive (" . ini_get("upload_max_filesize") . ") in php.ini.";
           break;
       case
UPLOAD_ERR_FORM_SIZE:
           echo "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.";
           break;
       case
UPLOAD_ERR_PARTIAL:
           echo "The uploaded file was only partially uploaded.";
           break;
       case
UPLOAD_ERR_NO_FILE:
           echo "No file was uploaded.";
           break;
       case
UPLOAD_ERR_NO_TMP_DIR:
           echo "Missing a temporary folder.";
           break;
       case
UPLOAD_ERR_CANT_WRITE:
           echo "Failed to write file to disk";
           break;
       default:

           echo "Unknown File Error";
    }
}
?>



Is het bestand leeg?

Als iemand een leeg bestand doorstuurt dan is het uploaden zelf wel gelukt, maar het bestand zelf is nutteloos, dus daar kun je op controleren.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
if ($_FILES['naam_formveld_uploadfile']['size'] == 0)
{

   echo "Lege file? Uploaden niet gelukt.";
}

?>


De inhoud van het bestand controleren

Hackers willen nog wel eens proberen om foute data te uploaden door b.v. een plaatje te vullen met javascript (Een bug uit IE7), of een plaatje dusdanig op
te bouwen dat de de jpg functionaliteit van je browser crasht en het plaatje gaat uitvoeren als een programma.

Dit kun je voorkomen door de inhoud van het bestand te controleren.
finfo_file()

PHP heeft hiervoor de finfo extentie
MIME type via de browser

Een simpele maar onveilige methode is om te kijken naar het MIME-type dat de browser doorgaf. De browser gokt dat aan de hand van de eerste regel van het bestand dat wordt doorgestuurd.

Deze methode is vooral een snelle controle om te zien of je überhaupt iets binnen krijgt wat jij verwacht. Als het MIME-type zegt dat het een foto is terwijl jij een zipje verwacht, dan hoef je de finfo niet eens aan te spreken want dan kan het sowieso geen zipje zijn.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$aMimetypes
= array('image/jpeg'
  ,'image/pjpeg'
  ,'image/gif'
  ,'image/png'
 );

$sMimetype = trim($_FILES['naam_formveld_uploadfile']['type']);

if (! in_array($sMimetype, $aMimetypes ))
{

  echo 'Deze foto heeft mime-type ' . htmlspecialchars($mimetype) . ' en alleen plaatjes met mime-type '.implode(', ',$aMimetypes).' worden geaccepteerd.';
}

?>



Extensie

Controleer of het bestand wel een goede extensie heeft.
Dit is snel, maar is geen sterke beveiliging!

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
  $aExtensions
= array(
      'jpg'
    , 'jpeg'
    , 'gif'
    , 'png'
      );

$sOriginal_filename = basename($_FILES['naam_formveld_uploadfile']['name']);

$sExtension = strtolower(substr($sOriginal_filename, 1+strrpos($sOriginal_filename, '.') ));
if (! in_array($sExtension, $aExtensions))
{

  echo 'Deze foto heeft als bestandsextensie ' . htmlspecialchars($sExtension) . ', maar alleen extensies '.implode(', ',$aExtensions).' worden geaccepteerd.';
}

?>
  



Move_upload_file

move_uploaded_file() zal FALSE teruggeven als er iets mislukt.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
$target
= '/compleet/path/waar/wil/je/file.ext';  // compleet path mét filename!

if (!move_uploaded_file($_FILES['naam_formveld_uploadfile']['tmp_name'],  $target))
{

  echo '<b>Foto upload mislukt!</b>';
}

?>


Veelgemaakte fouten

  • copy()
    De bestanden die zijn doorgestuurd worden door PHP op een tijdelijke lokatie opgeslagen. Daarvandaan moeten ze worden verplaatst of gekopieerd naar hun uiteindelijke bestemming. Dit moet je niet met copy() doen maar altijd met move_uploaded_file(). Waarom: move_uploaded_file() controleert of het bestand dat verplaatst wordt afkomstig is van een upload actie. Als een hacker het voor elkaar krijgt om een andere bestandsnaam aan move_uploaded_file() te voeren dan zal move_uploaded_file() herkennen dat dat bestand niet uit een upload komt en weigeren het bestand te verplaatsen.
    copy() kopieert elk willekeurig bestand waar het rechten voor heeft, en dat kan ook jouw htpasswd bestand zijn.
  • chmod 777
    Alle bestanden die PHP aanmaakt, kan PHP ook weer lezen. De enige uitzondering daarop zijn servers waar de beheerder het fout zit te doen. Als je een geüpload bestand niet kunt benaderen dan ligt het dus meestal NIET aan de rechten en moet je ook zeker NIET meteen gaan chmodden.
    Controleer de paden! Negen van de tien problemen bij het niet kunnen benaderen van bestanden ligt aan het pad.
  • Bij move_uploaded_file() is het verplicht om in de tweede parameter ook een nieuwe naam voor het bestand op te geven. De naam die het bestand had op de cliënt wordt niet gebruikt omdat dat extreem onveilig is: een hacker zou een naam kunnen opgeven als 'index.php' en dan een stuk php uploaden dat jouw site uit de lucht haalt. Je zult zelf een nieuwe naam moeten verzinnen om te gebruiken. (gebruik daar dus niet zelf alsnog de originele naam voor!!). Dat voorkomt tevens een probleem als meerdere keren een bestand genaam foto.jpg wordt geüpload en daarmee dus steeds de oude overschrijft.



Deze tutorial heeft oorsponkelijk gestaan op wiki.pfz.nl

« Lees de omschrijving en reacties

Inhoudsopgave

  1. Uploaden

PHP tutorial opties

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.