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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
|
<?xml version="1.0" encoding="iso-8859-1"?>
<chapter id="features.file-upload">
<title>Bestanden uploaden naar server</title>
<sect1 id="features.file-upload.post-method">
<title>Met de POST methode uploaden</title>
<simpara>
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.
</simpara>
<para>
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 <link linkend="features.file-upload.put-method">
PUT Methode Ondersteuning</link> voor meer details.
</para>
<para>
Een 'bestands upload' scherm kan gemaakt worden met een speciaal form
dat er zo uit ziet:
<example>
<title>Bestand Upload Form</title>
<programlisting>
<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>
</programlisting>
</example>
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.
</para>
<para>
In PHP 3 worden de volgende variablen gevuld in het script
zodra de upload succesvol is afgerond. (aangenomen wordt dat
<link linkend="ini.register-globals">register_globals</link>
aan is gezet in <filename>php3.ini</filename>). Als <link
linkend="ini.track-vars">track_vars</link> aanstaat zijn ze (ook) te
vinden in de globale array <varname>$HTTP_POST_VARS</varname>.
Let op: De variablen in het volgende voorbeeld hebben de prefix
'userfile' zoals aangegeven is in het bovenstaande voorbeeld:
<itemizedlist>
<listitem>
<simpara>
<varname>$userfile</varname> - De tijdelijke bestandsnaam
waarin het geuploade bestand is opgeslagen op de server.
</simpara>
</listitem>
<listitem>
<simpara>
<varname>$userfile_name</varname> - De originele naam of
het originele pad van het bestand op het systeem van de gebruiker.
</simpara>
</listitem>
<listitem>
<simpara>
<varname>$userfile_size</varname> - De grootte van het
'ge-uploade' bestand in bytes.
</simpara>
</listitem>
<listitem>
<simpara>
<varname>$userfile_type</varname> - Het mime-type van het bestand
als de browser deze informatie heeft meegestuurd. Een voorbeeld
zou zijn: "image/gif".
</simpara>
</listitem>
</itemizedlist>
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.
</para>
<para>
PHP 4 gedraagt zich enigzins anders, in PHP4 word de globale array
<varname>$HTTP_POST_FILES</varname> aangemaakt waarin informatie over
het ge-uploade bestand wordt opgeslagen. Deze is alleen te gebruiken
als <link linkend="ini.track-vars">track_vars</link> is aangezet.
In alle versies na PHP 4.0.2 staat deze echter standaard aan.
</para>
<para>
De inhoud van <varname>$HTTP_POST_FILES</varname> is als volgt:
(Hier word weer gebruik gemaakt van "userfile" zoals in het
bovenstaande voorbeeld.)
<variablelist>
<varlistentry>
<term><varname>$HTTP_POST_FILES['userfile']['name']</varname></term>
<listitem>
<para>
De originele naam van het bestand op het systeem van de gebruiker.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$HTTP_POST_FILES['userfile']['type']</varname></term>
<listitem>
<para>
Het mime-type van het bestand als de browser deze informatie
meegestuurd heeft. Bijvoorbeeld:
<literal>"image/gif"</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$HTTP_POST_FILES['userfile']['size']</varname></term>
<listitem>
<para>
De grootte van het ge-uploade bestand in bytes.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$HTTP_POST_FILES['userfile']['tmp_name']</varname></term>
<listitem>
<para>
De tijdelijke bestandsnaam waarin het ge-uploade bestand is
opgeslagen op de server.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Ge-uploade bestanden worden standaard in de standaard tijdelijke
directory van de server opgeslagen, tenzij er een andere locatie
is opgegeven met het
<link linkend="ini.upload-tmp-dir">upload_tmp_dir</link> directive in
<filename>php.ini</filename>. De server zijn standaard tijdelijke
kan worden veranderd worden door de 'environment' variable
<envar>TMPDIR</envar> te veranderen in het 'environment' waar PHP
in draait. Dit kun je <emphasis>niet</emphasis> doen in een script
met de PHP functie <function>putenv</function>. Deze 'environment'
variable kan ook gebruikt worden om te controleren of bewerkingen
op ge-uploade bestanden wel juist werken.
<example>
<title>Validating file uploads</title>
<para>
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 <function>is_uploaded_file</function> en
<function>move_uploaded_file</function>.
</para>
<programlisting role="php">
<?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");
?>
</programlisting>
<para>
Voor eerdere versies van PHP zal je iets als het volgende moeten
gebruiken.
<note>
<para>
Dit zal <emphasis>niet</emphasis> 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.
</para>
</note>
</para>
<programlisting role="php">
<?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'.";
}
?>
</programlisting>
</example>
</para>
<simpara>
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 <varname>$file_size</varname>
variable. Je kunt de <varname>$file_type</varname> 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.
</simpara>
<simpara>
Het bestand zal worden verwijderd uit de tijdelijke directory aan
het einde van het script als het bestand niet verplaatst of hernoemd is.
</simpara>
</sect1>
<sect1 id="features.file-upload.common-pitfalls">
<title>Standaard valkuilen</title>
<simpara>
Het veld MAX_FILE_SIZE kan geen grotere bestandsgrootte opgeven dan
de maximale grootte die is aangegeven met upload_max_filesize in php.ini
of met het php_upload_max_filesize Apache .conf directive.
Standaard is de maximale grootte 2 Megabytes.
</simpara>
<simpara>
Als je niet controleert of je op het juiste bestand bewerkingen
uitvoert, kunnen gebruikers hiervan misbruik maken en gevoelige
informatie in andere directories benaderen.
</simpara>
<simpara>
Let op: CERN httpd haalt alles voor de eerste spatie weg in de
content-type mime header die gestuurd word door de gebruiker.
Zolang CERN httpd dit doet ondersteunt PHP voor deze server
niet de bestands-upload mogelijkheid.
</simpara>
</sect1>
<sect1 id="feature-fileupload.multiple">
<title>Meerdere bestanden uploaden</title>
<simpara>
Het is mogelijk meerdere bestanden tegelijk te uploaden. Deze
informatie kun je ge-ordend in arrays verkrijgen. Om dit mogelijk
te maken moet je dezelfde syntax gebruiken als bij een HTML form
met meerdere selects en/of checkboxes.
</simpara>
<note>
<para>
Ondersteuning voor meerdere file uploads werd toegevoegd in
versie 3.0.10.
</para>
</note>
<para>
<example>
<title>Meerdere bestanden uploaden</title>
<programlisting>
<form action="file-upload.php" method="post" enctype="multipart/form-data">
Send these files:<br>
<input name="userfile[]" type="file"><br>
<input name="userfile[]" type="file"><br>
<input type="submit" value="Send files">
</form>
</programlisting>
</example>
</para>
<simpara>
Als het bovenstaande form verstuurd wordt, worden de globale arrays
<computeroutput>$userfile</computeroutput>,
<computeroutput>$userfile_name</computeroutput> and
<computeroutput>$userfile_size</computeroutput> aangemaakt in
de globale scope (ook $HTTP_POST_FILES (PHP 4) en $HTTP_POST_VARS (PHP 3)
worden aangemaakt.) Deze arrays zijn numeriek geindexeerde arrays met de
juiste waarden voor de ge-uploade bestanden.
</simpara>
<simpara>
Bijvoorbeeld, stel dat de bestanden
<filename>/home/test/review.html</filename> en
<filename>/home/test/xwp.out</filename> ge-upload worden.
In dit geval zou <computeroutput>$userfile_name[0]</computeroutput>
de waarde <computeroutput>review.html</computeroutput> en
<computeroutput>$userfile_name[1]</computeroutput> de waarde
<computeroutput>xwp.out</computeroutput> bevatten. Navolgend
zou <computeroutput>$userfile_size[0]</computeroutput> de grootte
van het bestand <filename>review.html</filename>'s bevatten,
enzovoort.
</simpara>
<simpara>
<computeroutput>$userfile['name'][0]</computeroutput>,
<computeroutput>$userfile['tmp_name'][0]</computeroutput>,
<computeroutput>$userfile['size'][0]</computeroutput> en
<computeroutput>$userfile['type'][0]</computeroutput> zijn ook beschikbaar.
</simpara>
</sect1>
<sect1 id="features.file-upload.put-method">
<title>PUT methode ondersteuning</title>
<para>
PHP ondersteunt ook de HTTP PUT methode welke gebruikt wordt door
o.a. Netscape Composer en W3C Amaya. PUT aanvragen zijn veel simpeler
dan een bestand uploaden en zien er ongeveer als volgt uit:
<informalexample>
<programlisting>
PUT /pad/bestandsnaam.html HTTP/1.1
</programlisting>
</informalexample>
</para>
<para>
Dit betekent normaal gezien dat de server het bestand ook als
/pad/filename.html wilt opslaan. Dit is natuurlijk geen goed idee
omdat je niet wilt dat anderen bestanden overschrijven in je web tree.
Om zo'n 'request' te verwerken vertel je je server eerst met wat voor
PHP script je dit request wilt verwerken. Met Apache kun je dit doen
met het <emphasis>Script</emphasis> directive. Het kan ongeveer
overal in je configuratie bestand geplaatst worden. Een standaard
plaats hiervoor is bijvoorbeeld een <Directory> blok.
Een enkele regel als voorbeeld:
<informalexample>
<programlisting>
Script PUT /put.php
</programlisting>
</informalexample>
</para>
<simpara>
Dit vertelt Apache om alle PUT requests waarvoor URIs die overeenkomen
met de context waarin deze regel geplaatst is, naar het put.php script
te sturen. We gaan er vanuit dat je de juist mime-headers heb gebruikt
om PHP met de .php extensie te laten werken en dat PHP actief is.
</simpara>
<simpara>
In je 'put.php' zou je dan iets als volgt neer zetten:
</simpara>
<para>
<informalexample><programlisting>
<? copy($PHP_UPLOADED_FILE_NAME,$DOCUMENT_ROOT.$REQUEST_URI); ?>
</programlisting></informalexample>
</para>
<simpara>
Dit kopieert het bestand naar de locatie welke gevraagd werd in
het request. Waarschijnlijk zal je nog enige tests uitvoeren op
het bestand voordat je het bestand daadwerkelijk kopieert. De enige
truc hier is dat PHP het bestand opslaat in een tijdelijk bestand
zoals bij de
<link linkend="features.file-upload.post-method">POST-methode</link>.
Zogauw het request is afgehandeld word het tijdelijke bestand verwijderd.
Let dus op dat je script het tijdelijke bestand verplaatst of hernoemd.
De naam van dit tijdelijke bestand is opgeslagen in de variable
<varname>$PHP_PUT_FILENAME</varname> en je kunt de voorgestelde locatie
vinden in <varname>$REQUEST_URI</varname> (Dit kan anders zijn bij
niet-Apache web servers). Dit is nogmaals een suggestie van de
gebruiker. Je hoeft deze suggestie niet te gebruiken, je kunt
bijvoorbeeld alle bestanden in een speciale uploads directory plaatsen.
</simpara>
</sect1>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->
|