Ajax-szerű fájlfeltöltés PHP-val
Ma elég huzamos ideig törtem a fejem és bújtam a fórumokat mire sikerült találnom egy olyan megoldást, amivel fel tudok tölteni egy fájlt anélkül, hogy frissülne az oldal. Hogy ez miért is kellett? A Kajdócsi Építész Stúdió adminisztrációs felületén dolgoztam és – bár később szántam-bántam, de – azt találtam ki, hogy amikor egy bizonyos bejegyzést – esetünkben munkát – szerkeszt az ember, lehessen “on-the-go” fájlokat feltölteni. Nem akarjuk ugyanis egy külön elküldött form miatt az összes módosítást elveszteni, ugye?
Szóval nekiálltam, hogy akkor megtanulom a jQuery Ajax metódusait, de szerencsére ráakadtam egy nagyon hasznos kis kerülőre. Ezt fogom most megosztani veletek.
Az első és legfontosabb dolog, hogy megértsük a <form> működését. A form – magyarul űrlap – egy olyan HTML tag, amivel egyszerű kitölthető mezőket tolhatunk a felhasználó arcába, ezzel rákényszerítve, hogy regisztrációkor megadja nekünk a haja színét és a kedvenc parfümének illatát. Ezek közé a mezők közé tartozik a fájl mező is. Az űrlap működése nagyon egyszerű, beillesztésekor megadjuk, hogy milyen módon (method), és hova (action) küldje az információkat, amiket a mezőkben megadtak a felhasználók.
A milyen módon rész POST vagy GET lehet, attól függően, hogy mennyire titkosan akarjuk küldeni az infokat. Elég másként lehet feldolgozni az adatokat, a GET ugyanis a címsorban küldi az adatokat (pl regisztracio.php?felhasznalo=jozsi&jelszo=123456), míg a POST titkosan küldi tovább, de ezért ha használni akarunk egy-két adatot további oldalakhoz, akkor azokat tovább kell vinni valahogy (PHP-nál nagyjából úgy mint ahogy a GET metódus teszi).
Az űrlap hova része a feldolgozó fájl (esetünkben egy PHP lesz), ami kezeli a megkapott adatokat és tárolja vagy továbbküldi.
A formokban betöltött fájlokkal az a baki összesen, hogy azokat PHP-ban nem $_POST és nem is $_GET, hanem $_FILES előtaggal kell feldolgoznunk, hogy jussunk valahova. Ahhoz, hogy megkapjuk a kiválasztott fájlokat, az űrlapnak meg kell adnunk még egy attribútumot, ez pedig az enctype. Az enctype igazából az elküldött adatok titkosításának módja (nem ugyanaz mint a POST/GET), a fájlok feltöltéséhez szükséges értéke pedig enctype=”multipart/form-data”.
Nézzük is akkor hogy mire lesz szükségünk. Lesz egy form, ahol kiválasztjuk a fájlt; lesz egy PHP ami feldolgozza a fájlt; és egy JavaScript ami a vizualizációért felelős. Az űrlap nem lesz túl bonyolult, lássuk csak:
<form action="upload.php" method="post" enctype="multipart/form-data" target="upload_target" >
Fájl: <input name="myfile" type="file" />
<input type="submit" name="submitBtn" value="Upload" />
</form>
Igazából néhány extra mezőre szükségünk lesz, hogy a JS is jól működjön:
<body>
<p id="f1_upload_process">Feltöltés folyamatban...</p>
<p id="result"></p>
<form action="upload.php" method="post" enctype="multipart/form-data" target="upload_target" onsubmit="startUpload();" >
Fájl: <input name="myfile" type="file" />
<input type="submit" name="submitBtn" value="Feltöltés" />
</form>
<iframe id="upload_target" name="upload_target" src="#" style="width:0px; height:0px; border:0px;"></iframe>
</body>
Mint látjátok bekerült két <p> bekezdés és egy <iframe> belső frame, de ez utóbbi el van rejtve (width: 0px, height: 0px;). A keretre azért van szükségünk, mert ha megnézitek, az űrlapunk megkapta target attribútumnak az <iframe> nevét; magyarán oda fog betöltődni az action=”upload.php”. Ezzel le is lőttem a legnagyobb poént, amivel a fájlfeltöltés AJAX-szerűvé válik. Egy finom kis CSS-t ráhúzunk az oldalra:
#f1_upload_process{
z-index: 100;
position: absolute;
visibility: hidden;
}
Ezzel biztosítottuk, hogy a #f1_upload_process egyelőre láthatatlan legyen, mert majd a JavaScript teszi láthatóvá, a fájlfeltöltés elindításakor. Sok szó esett már a JavaScript részről, nézzük is meg, hogy mit tud. Egyelőre csak a startUpload() függvényt hívtuk meg az űrlap elküldésével. Ez a függvény igazából csak annyit tesz, hogy a már említett #f1_upload_process részt megmutatja nekünk és engedélyezi a form elküldését:
function startUpload(){
document.getElementById('f1_upload_process').style.visibility = 'visible';
return true;
}
A hangsúly nem is ezen a függvényen van, hanem a stopUpload()-on, ami a feltöltés eredményét fogja nekünk kiírni. Ezt a függvényt a PHP fájlból fogjuk meghívni majd.
function stopUpload(success) {
if (success == 1){
document.getElementById('result').innerHTML = '<span class="msg">Sikeres volt a fájlfeltöltés!</span>>';
} else {
document.getElementById('result').innerHTML = '<span class="emsg">Hiba történt a feltöltés során!</span>';
}
document.getElementById('f1_upload_process').style.visibility = 'hidden';
return true;
}
A függvényt egy success paraméterrel együtt hívhatjuk meg, ami az eredménynek megfelelő üzenetet dob ki a <p id=”result”> bekezdésünkbe. A vizualizációval meg is volnánk, nézzük meg, hogy mi is történik a háttérben. A PHP az űrlapból megkapott fájlt egyszerűen felmásolja a gyökérkönyvtárjába, majd 1 másodperces pihenő után (hogy a nagyon kicsi fájloknál is látszódjon, hogy történik valami
) meghívja a stopUpload() JS függvényt.
<?php
$destination_path = getcwd().DIRECTORY_SEPARATOR;
$result = 0;
$target_path = $destination_path . basename( $_FILES['myfile']['name']);
if(move_uploaded_file($_FILES['myfile']['tmp_name'], $target_path)) {
$result = 1;
}
sleep(1);
echo('<script language="javascript" type="text/javascript">
window.top.window.stopUpload(' . $result . ');
</script> ');
?>
Ezzel tulajdonképpen meg is volnánk. A dolog működik szépen, én is használom, használjátok ti is egészséggel! Ha bármilyen kérdés vagy észrevétel van, jöhet fórumba!
Forrás: ajaxf1.com



![[gif] Apple, fix the Smart folders icon!](http://dribbble.com/system/users/4182/screenshots/344218/fixthesmartfolders_teaser.gif?1323248533)

Comments
January 9, 2010 12:53 am
Hmm nagyon tetszik! Ezt ki fogom próbálni, pont szükségem volt egy ilyen szkripre::))
January 6, 2011 10:49 pm
Nagyon hasznos és jó cikk. Gratulálok.
February 10, 2011 10:47 pm
Így minden file típus feltölthető a serverre. Hogyan lehetne azt beállítani, hogy csak zip vagy rar file-oket lehessen feltölteni, semmilyen más típust ne (főleg ne php-t vagy exe-t)?
February 10, 2011 10:56 pm
A php fájlban be kell tenni egy ellenőrzés, hogy csak abban az esetben másolja a fájlt, ha az bizonyos típusú. Ezt teheted többféleképpen is.
- Ellenőrzöd a fájl kiterjesztését (utolsó pont után lévő betűk ellenőrzése a fájlnévben).
- Ellenőrzöd a “$_FILES["uploaded_file"]["type"]“-ban megadott MIME típust. Ezt a böngésző küldi a feltöltőnek, tehát nem lehet mondjuk exe fájlt jpg kiterjesztéssel feltölteni, ha jól tudom. Nézz utána ezeknek a típusoknak, mert nem minden van, de ez egyszerű és biztonságos.
March 21, 2011 10:07 pm
Szia Zoli,
tényleg frankó ez a cucc, de ki szeretném bővíteni egy aprósággal. Hogyan tudnám úgy módosítani, hogy maxfilesize-zal checkolja a méretét? php-ban működik, de ez az ajaxos téma nekem kicsit új…
Köszi a helpet!
March 23, 2011 9:52 pm
A legjobb szerintem az lehet, hogy a PHP fájlba beleraksz egy feltételt, hogy ha a küldött fájl nagyobb mint a maxfilesize, akkor mondjuk resultnak 2-t ír ki, ezt a 2-t pedig a javascriptben lekezeled, és visszaadsz egy hibaüzenetet, hogy nagy a fájl, kb így:
PHP
[...]
$limitsize = 50000; //50000 kilobyte fájlméret
if ($_FILES['myfile']['size'] > $limitsize) {
if (move_uploaded_file($_FILES['myfile']['tmp_name'], $target_path)) {
$result = 1;
}
} else $result = 2;
[...]
JS:
[...]
if (success == 1){
document.getElementById(‘result’).innerHTML = ‘Sikeres volt a fájlfeltöltés!>’;
} else if (success == 2) {
document.getElementById(‘result’).innerHTML = ‘Túl nagy a fájl!‘;
} else {
document.getElementById(‘result’).innerHTML = ‘Hiba történt a feltöltés során!‘;
}
[...]
Szerintem ennek így működnie kéne, gyors ránézésre, de ne vedd biztosra. Hajrá
February 1, 2012 5:37 pm
Szia Zoli, nekem egy olyan kérdésem van, hogy arra van-e lehetőség, hogy egy inputba bekérek egy nevet, majd ezt a nevet felhasználva a létrehozzon egy mappát( ahol kisbetűsre alakít és az ékezetes karaktereket eldobja)
February 1, 2012 10:38 pm
Persze van rá lehetőség! Annyit kell tenned, hogy a formba beteszel egy input mezőt, amiben bekéred a mappa nevet, majd az upload.php-ban elvégzed ennek az átalakítását (kisbetűsítés, speciális karakterek átalakítása) és ellenőrzését (van-e már ilyen mappa, ha nincs létre kell hozni).
Mivel a php minden form mezőt megkap POST elemként, ezért nem nehéz lekezelni ezeket a dolgokat.
A mappanév átalakításra szerintem keress valamilyen egyszerű scriptet, ami ilyenre alkalmas, biztos van belőle neten pár