19. Fejezet. Fájlfeltöltés kezelése

Tartalom
POST metódusú feltöltések
Tipikus csapdák
Több fájl egyidejű feltöltése
PUT metódusú feltöltések

POST metódusú feltöltések

A PHP alkalmas fájl feltöltést fogadni bármilyen RFC-1867 kompatibilis böngészőtől (mint a Netscape Navigator 3 vagy későbbi és a Microsoft Internet Explorer 3 Microsoft javítással, vagy későbbi IE javítás nélkül). Ez a szolgáltatás egyaránt lehetővé teszi a látogatónak szöveges és bináris fájlok feltöltését. A PHP azonosítási és fájlkezelési képességeivel teljes felügyeleted van afelett, hogy ki tölthet fel fájlt, és mi történik a feltöltött fájlokkal.

Érdemes megemlíteni, hogy a PHP támogatja a PUT metódust is, amit a Netscape Composer és a W3C Amaya kliensek használnak. Lásd a PUT metódusú feltöltések részt.

A fájl feltöltési lehetőség egy speciálisan kiképzett formmal biztosítható:

Példa 19-1. Fájlfeltöltő Űrlap


<form enctype="multipart/form-data" action="_URL_" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="1000">
Fájl elküldése: <input name="userfile" type="file">
<input type="submit" value="OK">
</form>

    
Az _URL_ a feldolgozást végző PHP fájlra kell, hogy mutasson. A MAX_FILE_SIZE rejtett mező a fájl input mező előtt kell, hogy szerepeljen, és azt adja meg, hogy mekkora a maximális fájl méret (byte-okban megadva), amit a PHP fogad.

Figyelem

A MAX_FILE_SIZE egy javasolt érték a böngészők számára. Könnyű megkerülni ezt a megadott maximumot. Ezért nem szabad arra építeni, hogy a böngésző úgy viselkedik, ahogy azt te szeretnéd. A PHP-beállítások a maximális feltöltési állományméretre azonban nem kerülhetőek meg.

PHP-ben a következő változók jönnek létre a célprogramban egy sikeres feltöltés után, feltéve, hogy a register_globals be van kapcsolva a php.ini fájlban. Ha a track_vars is be van kapcsolva, elérhetőek lesznek a $HTTP_POST_VARS globális tömbben is. Vedd figyelembe, hogy a következő változónevek első része onnan származik, hogy a fenti űrlapban a 'userfile' nevet adtuk a feltöltő input elemnek:

Figyeld meg, hogy a "$userfile" előtag minden fenti változóban a form-ban megadott érték, amit a TYPE=file sornál megadott INPUT elem neveként határoztál meg. A fenti kérdőívben ezt "userfile"-nak választottuk.

A PHP 4 viselkedése egy kicsit eltér ettől, mivel egy új $HTTP_POST_FILES globális asszociatív tömbben is visszaadja a feltöltött fájl információkat. Ez szintén csak akkor áll rendelkezésre, ha a track_vars be van kapcsolva, de a track_vars a PHP 4.0.2-nél későbbi verziókban mindig ba van kapcsolva.

A $HTTP_POST_FILES tömb tartalma itt következik. Ebben az esetben is feltételezzük, hogy a fenti űrlapnak megfelelően a 'userfile' nevet adtad a feltöltési input mezőnek:

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

Az eredeti fájlnév a kliensgépen.

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

A fájl MIME típusa, ha a böngésző megadta ezt az információt. Például egy gif kép esetében: "image/gif".

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

A feltöltött fájl mérete, byte-ban megadva.

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

Az ideiglenes fájl elérési útja, ahol a feltöltött fájl tárolásra került a szerveren.

A fájlok alapbeállításban a szerver szokásos ideiglenes könyvtárában tárolódnak, ha nem adtál meg mást az upload_tmp_dir beállítással a php.ini fájlban. A szerver alapbeállítású könyvtára megváltoztatható a TMPDIR környezeti változóval abban a környezetben, ahol a PHP fut. Egy PHP szkriptből a putenv()-el való átállítása nem fog menni. Ez a környezeti változó arra is használható, hogy ellenőrizd, hogy más műveletek is végezhetőek-e a feltöltött fájlokon.

Példa 19-2. Fájlfeltöltések ellenőrzése

Az alábbi példák PHP 3 esetén a 3.0.16-nál újabb verziókkal működnek, PHP 4 esetén a 4.0.2-nél újabbakkal. Lásd az is_uploaded_file() és move_uploaded_file() függvényeket.


<?php 
if (is_uploaded_file($userfile)) {
    copy($userfile, "/a/feltoltott/file/uj/helye");
} else {
    echo "Lehetséges támadás. Fájlnév: '$userfile'.";
}
/* ...vagy... */
move_uploaded_file($userfile, "/a/feltoltott/file/uj/helye");
?>

     

A PHP előző verzióiban valami hasonlót kell csinálnod, mint amit az alábbiakban bemutatunk.

Megjegyzés: Ez nem fog működni a PHP 4-es 4.0.2-nél újabb verzióiban, mivel egy olyan belső elemre épít, ami a későbbi verziókban megváltozott.


<?php 
/* Feltöltött fájl tesztelése */ 
function is_uploaded_file($filename) {
    if (!$tmp_file = get_cfg_var('upload_tmp_dir')) {
        $tmp_file = dirname(tempnam('', ''));
    }
    $tmp_file .= '/' . basename($filename);
    /* lehet, hogy a user befejező perjelet adott meg az iniben... */
    return (ereg_replace('/+', '/', $tmp_file) == $filename);
}

if (is_uploaded_file($userfile)) {
    copy($userfile, "/a/feltoltott/file/uj/helye");
} else {
    echo "Lehetséges támadás. Fájlnév: '$userfile'.";
}
?>

     

A PHP program, ami megkapja a feltöltött fájlt, gondoskodik arról is, hogy a kívánt műveleteket elvégezze a fájlal. Például törölheti a fájlt, ha az túl nagy, vagy túl kicsi, figyelembe véve a $..._size változót, vagy meghatározhatja a $..._type alapján, hogy ez a fájl megfelel-e egy meghatározott fájltípusnak, és ha nem, törölheti. Bármi is a cél a feltöltött fájlal, a PHP szkriptnek kell gondoskodnia arról, hogy elmozgassa egy biztonságos helyre, vagy törölje az ideiglenes könyvtárból az adott fájlt.

A fájl törlésre kerül az ideiglenes könyvtárból a kérés végrehajtásának végeztével, ha nem mozgatod el, vagy nem nevezed át.