Ubacivanje slika ili drugih fajlova
U PHP-u postoje funkcije za upload fajlova korišćenjem specijalno ugrađenog
(sistemskog) niza $_FILES. Evo skripte koja ubacuje
slike preko forme i ujedno ispisuje tekst na slici:
<html><head><title>Upload slika</title><meta
http-equiv="Content-Language" content="sr">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250">
</head><body><h2>Upload slika</h2><hr>
<?
if ($_POST"SBgumb"]!="Posalji"){
?>
<form method="POST" action="" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="20480">
<input type="file" size="25" name="slika"><br>
<input type="submit" name="SBgumb" value="Posalji">
<input type="reset" value="Reset">
</form>
<?
}else{
if ($_FILES ['slika']['error'] > 0){
echo 'Problem:';
switch ($_FILES ['slika']['error']){
case 1: echo 'Slika je prevelika pokusajte ponovo'; break;
case 2: echo 'Slika je prevelika pokusajte ponovo'; break;
case 3: echo 'Slika nije potpuno ucitana, pokusajte ponovo';
break;
case 4: echo 'Slika nije ucitana, pokusajte ponovo'; break;
case 6: echo 'Serverska greska, pokusajte ponovo'; break;
case 7: echo 'Slika nije ucitana, pokusajte ponovo'; break;
case 8: echo 'Slika nije ucitana, pokusajte ponovo'; break;
}
exit;
}
if ($_FILES ['slika']['size'] > 20480) { echo 'Slika je prevelika
pokusajte ponovo'; exit;}
if ($_FILES ['slika']['type']=='image/jpeg'){ $a="ok"; $b="jpg";}
if ($_FILES ['slika']['type']=='image/png'){ $a="ok"; $b="png";}
if ($a!="ok"){ echo'Problem: slika nije u okviru ponudjenih formata
jpg i png, pokusajte ponovo)'; exit;}
$upfile = $_FILES ['slika']['name'];
if ( is_uploaded_file ($_FILES ['slika']['tmp_name'])){
if ( !move_uploaded_file ($_FILES ['slika']['tmp_name'], $upfile)){
echo 'Problem: Nije premestena slika u sajt';
exit;
}
}else{
echo 'Problem: Nismo ucitali sliku pod nazivom:';
echo $_FILES ['slika']['name'];
exit;
}
include 'povzi.php';
$sql = "INSERT INTO slike (naziv) VALUES ('$upfile')";
if (!mysql_query ($sql)) { echo "Nastala je greška pri unosu naziva slike
u bazu podataka";}
if ($b == "jpg"){ header ("location: jpeg.php?ime=$upfile");}
if ($b == "png"){ header ("location: png.php?ime=$upfile");}
}
?>
</body></html>
Prvi red forme za upload podataka je:
<form method="POST" action="" enctype="multipart/form-data">
Nakon toga skriveno hidden polje OBAVEZNO se
ubacuje pre polja za unos podataka, i UVEK se mora pisati. Ako ga izostavimo
forma neće raditi!
<input type="hidden" name="MAX_FILE_SIZE" value="20481">
Uvek se u "name" piše MAX_FILE_SIZE. U "value" se
definiše maksimalna veličina fajla koga uplodujemo preko forme. To je broj
izražen u bajtima. Na primer ako želimo da maksimalna veličina fajla ne bude
veća od 20 kB onda pišemo 20480 (20 x 1024). Sledeće polje je zapravo polje za
upload:
<input type="file" size="25" name="slika">
Pod "size" odredjujemo broj znakova polja za upis kojeg vidimo u brouzeru. Pod
"name" definišemo programsko ime fajla kojim baratamo kroz program (u našem
slučaju kao što vidimo je na primer "slika", a možemo ga imenovati kako nam je
volja).
Nakon submitiranja superglobalna promenjljiva $_FILE
iz HTML forme "skuplja" sledeće vrednosti:
- $ _FILES['slika']['name'] – Vrednost ove globalne promenjljive je naziv fajla kao što je u brouzeru korisnika.
- $ _FILES['Userfile']['type'] – Vrednost je string tipa podataka. Na primer ako je
gif slika uplodovana preko forme onda će vrednost biti string "image/gif". Ostali tipovi slika
mogu biti na primer: "image/jpeg", "image/png" i tako dalje.
- $ _FILES['Userfile']['size'] –
Vrednost je ceo broj koji je jednak veličini uplodovanog fajla u bajtima.
Ovo je jako bitna promenjljiva za bezbednost sajta, kao što
će mo videti u nastavku.
- $_FILES['userfile']['tmp_name'] – Privremeni direktorij gde će fajl biti smešten na serveru. Kada se završi izvršavanje skripte taj privremeni direktorij biće izbrisan
tako da ako želimo zapamtiti sliku ili fajl moramo pre toga odredjenom
funkcijom zapamtimo uplodovan fajl.
- $_FILES['Userfile']['error'] – Ukoliko smo iz forme izašli sa nekom greškom (na primer fajl je veći nego što smo odredili) ova globalna varijabla će je zapamtiti pomoću celih brojeva, pa tako biće:
- 0 – Nema greške.
- 1 – fajl koji je pokušan da se uploduje premašuje vrednost koju smo zadali u formi (u našem slučaju je u hidden polju value = 20481 ili ti 20kB). Ali ovo nije dovoljno za bezbednost jel posetilac može sam izraditi formu koja će slati veće slike na našu adresu. Zato je potrebno proveriti veličinu slike redkom u kodu if ($_FILES['slika']['size'] > 20480)
- 2 – Skoro isto kao u tački 1 (da ne komplikujemo).
- 3 – Datoteka je učitana delimično.
- 4 – Datoteka (fajl) nije učitana, odnosno nema je.
- 6 – Nedostaje privremena mapa (uvedeno u PHP 4.3.10 i novije).
- 7 - Neuspelo pisanje datoteke na hard disku hosta. Uvedena u PHP 5.1.0.
- 8 – Zaustavljena ekstenzija upload fajla. Uvedena u PHP 5.2.0.
Sve ove greške proveravamo sledećim kodom:
if ($_FILES['slika']['error'] > 0){
echo 'Problem:';
switch ($_FILES['slika']['error']){
case 1: echo 'Slika je prevelika pokusajte ponovo'; break;
case 2: echo 'Slika je prevelika pokusajte ponovo'; break;
case 3: echo 'Slika nije potpuno ucitana, pokusajte ponovo'; break;
case 4: echo 'Slika nije ucitana, pokusajte ponovo'; break;
case 6: echo 'Serverska greska, pokusajte ponovo'; break;
case 7: echo 'Slika nije ucitana, pokusajte ponovo'; break;
case 8: echo 'Slika nije ucitana, pokusajte ponovo'; break;
}
exit;
}
Nastavimo sada sa objašnjenjem našeg koda. U nastavku sledi ključni red za
bezbednost forme i unetih fajlova:
if ($_FILES['slika']['size'] > 20480){echo 'Slika je prevelika pokusajte ponovo'; exit;}
Naime, rekli smo da u formi u skrivenom polju, pomoću vrednosti "value"
ograničavamo veličinu slike/fala koji se može ubaciti. Medjutim skriveno je u
smislu da je nevidljivo u internet pregledniku ali ako stranu skinemo sa neta i
ubacimo u nekom HTML programu za editovanje neće biti nevidljivo. Naime želim da
kažem da zlonamerni posetilac može napraviti sam formu koja će slati veličinu
slike po njegovoj volji na našu skriptu za upload. Sistemski niz
$_FILES ['Userfile'] ['error'] sa svojim
vrednostima nam ne može pomoći jer on samo čita i prati sve ono što radi forma.
Za pravu zaštitu zapravo služi sistemska promenjljiva
$_FILES['slika'] ['size'] jer sistem u njoj kao vrednost smešta pravu
veličinu privremeno uplodovane slike bez ikakve veze sa formom. I sada uporedimo
tu stvarnu veličinu slike sa onom koju mi očekujemo i ako je neko menjao formu
za slanje ne može da nas obmane.
if ($_FILES['slika']['type']=='image/jpeg'){$a= "ok"; $b="jpg";}
if ($_FILES['slika']['type']=='image/png'){$a="ok"; $b="png";}
if ($a != "ok"){ echo 'Problem: slika nije u okviru ponudjenih formata (jpg,
png)'; exit;}
Ovim kodom kao prvo i osnovno dajemo da se uploduju samo slike i to ne sve već
samo one koje imaju formate jpeg i png. Ako zadovoljava uplodovan format slike
tada je "zastavica" $a = "ok". Takodje tu smo i
definisali promenjljivu $b koju će mo kasnije
koristiti.
$upfile = $_FILES['slika']['name'];
if (is_uploaded_file ($_FILES['slika']['tmp_name'])){
if (!move_uploaded_file ($_FILES['slika']['tmp_name'], $upfile)){
echo 'Problem: Nije premesten slika u sajt';
exit;
}
}else{
echo 'Problem: Nismo ucitali sliku pod nazivom:';
echo $_FILES['slika']['name'];
exit;
}
E u ovom delu koda već konkretno trajno memorišemo fajl na hostu. Promenjljivom $upfile
odredjujemo ime slike. Ako želimo da je ime nepromenjeno sa onim koje je i
korisnik uneo pišemo kao u skripti a ako želimo da damo novo ime samo ga dodamo
kao string toj promenjljivoj. Takodje možemo odrediti i neki folder u kome će mo
smestiti našu sliku. U našem konkretnom slučaju folder je isti u kome je
smeštena i skripta za upload. Naravno sve to možemo promeniti recimo možemo
kreirati novi folder "slike" pa će biti:
$upfile = "/slike/".$_FILES["slika"]["name"];
Fukcija is_uploaded_file ( $_FILES ['slika']['tmp_name'] )
proverava da li postoji privremen uplodovan fajl $_FILES
['slika']['tmp_name']. Ako postoji funkcija vraća "true" i nastavlja sa
skriptom. Ako ne postoji privremeni uplodovan fajl funkcija vraća "false",
ispisuje "nismo ucitali sliku pod nazivom: ispisujemo
naziv fajla" i završavamo sa skriptom naredbom exit.
Funkcije koja služi za trajno prebacivanje privremenog fajla, na server je:
move_uploaded_file ($_FILES['slika']['tmp_name'], $upfile)
Znači ovim redom koda konačno sliku/fajl smeštamo na mesto u hostingu gde želimo
i pod kojim imenom želimo kao što smo definisali u promenjljivoj
$upfile. A ona privremena slika se briše nakon
izvršenja skripte.
Funkciju move_uploaded_file() smo smestili u
IF da bi ujedno proverili da li smo uspešno trajno
memorisali uplodovan fajl. Ako je sve ok onda IF
zbog znaka negacije " ! " ispred funkcije vraća
"false" i nastavljamo sa izvršenjem ostatka skripte, a ako je došlo do greške pa
fajl nije uplodovan trajno IF vraća "true" pa se
ispisuje tekst "Problem: Nije premesten slika u sajt"
i prekidamo sa izvršenjem skripte naredbom exit.
U nastavku skripte imamo sledeći deo:
include 'povzi.php';
$sql = "INSERT INTO slike (naziv) VALUES ('$upfile')";
if (!mysql_query ($sql)){
echo "Nastala je greška pri unosu naziva slike u bazu podataka";
}
Sada možemo naziv mesta na hostingu gde smo smestili fajl memorisati u bazu
podataka, to jest u konkretnom našem slučaju u tabeli "slike", kolona "ime".
Ovde ne moramo koristiti fnkciju addslashes () jer
u nazivima fajlova na hard disku ne mogu da se nadju naši nepoželjni znaci. Ono
što je bitno ovde je to da smo dakle u tabeli smestili samo "string" naziva
lokacije fajla a ne sam fajl. Možemo takodje smeštati i fajlove u bazu ali je
zbog brzine izvršavanja skripte bolje ovako.