11
Tags:
php
upload
filer
billeder
Skrevet af
Bruger #5620
@ 02.04.2011
Uploader-klassen
Det er objekter af Uploader-klassen, der håndterer behandlingen af den uploadet fil på serveren fra dennes midlertidige til den endelige placering. Formålet med uploader klassen er at indkapsulere håndteringen af den uploadet fil og $_FILES arrayet.
Det følgende UML diagram og kodeboks viser Uploader-klassen
- <?php
- class Uploader{
- private $destination = "";
- private $last_uploaded_file_name = "";
- private $allowed_file_types = array();
- private $errno = 0;
-
- public function set_destination($dest){
- $this->destination = $dest;
- }
-
- public function set_allowed_filetypes(){
- $this->allowed_file_types = func_get_args();
- }
-
- protected function check_allowed_filetype($type){
- return count($this->allowed_file_types) == 0 || array_search($type, $this->allowed_file_types)!==false;
- }
-
- public function get_name_of_uploaded_file(){
- return $this->last_uploaded_file_name;
- }
-
- public function post($fieldname){
- // check for PHP's built-in uploading errors
- $file = $_FILES[$fieldname];
- if( $file['error'] != 0){
- $this->errno = $file['error'] + 10;
- return false;
- }
-
- if(!is_uploaded_file($file['tmp_name'])){
- $this->errno = 3;
- return false;
- }
-
- if(!$this->verify($file['tmp_name'])){
- return false;
- }
-
- $info = pathinfo($file['name']);
- if(!$this->check_allowed_filetype($info['extension'])){
- $this->errno = 2;
- return false;
- }
-
- $file_name = $this->make_unique_name($file);
- if($this->upload_file($file['tmp_name'], $this->destination.$file_name)){
- $this->last_uploaded_file_name = $file_name;
- return true;
- }else{
- return false;
- }
- }
-
- protected function verify($filename){
- return true;
- }
-
- protected function upload_file($from, $to){
- if(!move_uploaded_file($from, $to)){
- $this->errno = 4;
- return false;
- }
- return true;
- }
-
- protected function make_unique_name($file){
- $now = time();
- $info = pathinfo($file['name']);
- $ext = $info['extension'];
- while(file_exists($this->destination.$now.'.'.$ext)){
- $now++;
- }
- return $now.'.'.$ext;
- }
-
- protected function set_errno($no){
- $this->errno = $no;
- }
-
- public function get_error_number(){
- return $this->errno;
- }
-
- public function get_error_message(){
- switch($this->errno){
- case 2: return 'The file type is not allowed';
- case 3: return 'This is not an uploaded file';
- case 4: return 'Could not move file to destination';
- case 11: return 'The file exceeds size ini directive';
- case 12: return 'The file exceeds size form directive';
- case 13: return 'file upload was only partial';
- case 14: return 'no file was attached';
- case 16: return 'no temporary directory for files';
- case 17: return 'can\'t write to disk';
- case 18: return 'an extension blocked upload';
- default: return 'This ('.$this->errno.') is not a known error id.';
- }
- }
- };
Hvert af de følgende afsnit forklarer en enkelt metode.
set_destination
Kaldes for at sætte stien til destinations folderen. Det skal være lovligt at skrive filer til denne folder. Dette bliver ikke direkte testet af klassen, men vil forårsage en fejl, hvis det ikke er lovligt.
- public function set_destination($dest){
- $this->destination = $dest;
- }
set_allowed_filetypes
Kaldes for at sætte typerne af de filer, der skal kunne uploades. Dette er filendelsen efter punktummet i filnavne. Metoden tager et variabelt antal strenge, hvor hver streng er en filendelse.
- public function set_allowed_filetypes(){
- $this->allowed_file_types = func_get_args();
- }
På linje 2 af koden kaldes funktionen "func_get_args". Dette er en indbygget PHP funktion, der returnerer alle argumenter givet til metoden som et array. I PHP kan metoder og funktioner tage et variabelt antal argumenter. Hvis argumenterne er strenge vil
func_get_args returnere et array af strenge.
check_allowed_filetype
Bruges til at teste, at filtypen, der er uploadet, er en af de tilladte typer. Metoden returnerer sandt ellers falsk.
- protected function check_allowed_filetype($type){
- return count($this->allowed_file_types) == 0 || array_search($type, $this->allowed_file_types)!==false;
- }
På linje 2 testes der om antallet af tilladte filtyper er nul, hvis dette er tilfældet returneres sandt ellers testes der om den filtype der er uploadet er i arrayet af lovlige filtyper, dette gøres med den indbygget PHP funktion
array_search. Denne funktion gives en værdi og et array og finder så indekset på værdien eller returnerer falsk. I denne metode vil vi kun vide om værdien er i arrayet så vi tester at funktionen returnerer en værdi forskellig fra false. Der er her vigtigt at det er !== og ikke blot != da denne sidste også er sandt på 0 som er et af de mulige indeks et array.
post
Rykker en fil fra dennes midlertidige placering til sin endelige placering og returnere sandt, hvis den fejler returneres falsk. Metoden gives navnet på på input-tagget i HTML-formen.
- public function post($fieldname){
- // check for PHP's built-in uploading errors
- $file = $_FILES[$fieldname];
- if( $file['error'] != 0){
- $this->errno = $file['error'] + 10;
- return false;
- }
-
- if(!is_uploaded_file($file['tmp_name'])){
- $this->errno = 3;
- return false;
- }
-
- if(!$this->verify($file['tmp_name'])){
- return false;
- }
-
- $info = pathinfo($file['name']);
- if(!$this->check_allowed_filetype($info['extension'])){
- $this->errno = 2;
- return false;
- }
-
- $file_name = $this->make_unique_name($file);
- if($this->upload_file($file['tmp_name'], $this->destination.$file_name)){
- $this->last_uploaded_file_name = $file_name;
- return true;
- }else{
- return false;
- }
- }
Linje 3, tager feltet fra $_FILES arrayet. Dette gøres udelukkende for at undgå at skulle skrive $_FILES['file'] hele tiden.
Det første der gøres er at teste om der opstod en fejl under upload af filen, dette gøres ved at teste om "error" feltet for filen er forskellig fra 0, linje 4. Hvis en felj opstod tages fejlnumret og der lægges 10 til dette som så gives til metoden set_errno, linie 5, da upload af filen er fejlet returneres falsk.
Hvis filen er blevet uploadet, kaldes PHP funktionen
is_uploaded_file, linje 9, med filens midlertidige placering. Denne funktion returnerer falsk, hvis hvad der er placeret i den midlertidige placering ikke er en uploadet fil. Hvis dette er tilfældet kaldes metoden set_errno med værdien 3 og der returneres falsk, linje 10 og 11.
Hvis filen er blevet uploadet og er en uploadet fil kaldes metoden verify med filens midlertidige placering, linje 14, hvis denne returnere falsk returnerer post falsk, linje 15.
For at finde ud af om den uploadet fil har en lovlig endelse bruges PHP indbygget funktion
pathinfo, der returnerer et associativt array med information over en givet filsti inklusiv filens endelse. Funktionen kaldes med filens navn på brugerens maskine, linje 18, grunden til dette er, at filendelse på den midlertidige fil ikke er den oprindelige endelse, men blot "tmp".
Den fundne filendelse gives til metoden check_allowed_filetype, linje 19, hvis denne returnerer falsk kaldes metoden set_errno med værdien 2 og der returneres falsk, linje 19 og 20.
Da filen nu er blevet vurderet lovlig kaldes metoden make_unique_name, linje 24, med filens information. Denne metode skal returnerer et unikt navn som kan gives til det uploadet fil.
Det unikke navn gives til metoden upload_file sammen med filens midlertidige placering, linje 25. Hvis denne metode returnerer sandt sættes "last_uploaded_file_name" til filens nye unikke navn og der returneres sandt, linje 26 og 27. Hvis metoden returnerer falsk returnerer post metoden falsk linje 29.
verify
Returnerer bare sandt. Det er tanken at klasser, der arver fra Uploader, kan implementere en anden udgave af denne og dermed ændre i, hvad post metoden tester.
- protected function verify($filename){
- return true;
- }
Metodens scope er sat til protected, linje 1. Grunden til dette er at det vil få PHP til at bruge en tilsvarende metode i en arvende klasse. Havde scope været sat til private ville post metoden altid bruge verify metoden i Uploader klassen og havde scope været sat til public var klassens brugergrænseflade blevet udvidet med en metode uden funktionalitet for brugeren.
upload_file
Rykker den midlertidige fil til dennes endelige placering.
- protected function upload_file($from, $to){
- if(!move_uploaded_file($from, $to)){
- $this->errno = 4;
- return false;
- }
- return true;
- }
Metodens scope er sat til protected, linje 1, med den samme begrundelse som brugt i verify metoden, her blot for at arvende klasser kunne gøre andet end at rykke filen til et sted på serveren.
Metoden kalder den PHP indbygget funktion
move_uploaded_file til at rykke en fil fra sin midlertidige placering til sin endelige placering. Denne funktion kan fejle og returnere falsk. Hvis den gør dette kaldes metoden set_errno med værdien 5 og der returneres falsk, linje 3 og 4, ellers returneres der sandt, linje 6. Funktionen kan fejle, hvis det ikke er lovligt at skrive til destinations folderen.
make_unique_name
Returnerer et unikt filnavn givet filens information i $_FILES.
- protected function make_unique_name($file){
- $now = time();
- $info = pathinfo($file['name']);
- $ext = $info['extension'];
- while(file_exists($this->destination.$now.'.'.$ext)){
- $now++;
- }
- return $now.'.'.$ext;
- }
Metodens scope er sat til protected, linje 1, med den samme begrundelse som brugt i verify metoden, her blot for at arvende klasser kan give en anden metode til et unikt filnavn.
Den indbygget PHP funktion
time bruges til at finde serverens tid som et helt antal sekunder, linje 2. Derefter kaldes pathinfo, se post metoden for forklaring af funktionen, for at finde filendelsen, linje 2 og 3. Der startes en while løkke der iterer så længe der eksisterer en fil med et navn bestående af antallet af sekunder og den oprindelige filendelse, linje 5. For hver iterering lægges der 1 til antallet af sekunder, linje 6. Når et unikt navn findes returneres dette.
Sandsynligheden for, at den før omtalte løkke, går meget galt er forsvindende lille for normale websteder. Men det kan gå galt da to brugerer i teorien kunne finde på at upload et billed med samme endelse på samme tidspunkt (Et interval på et par sekunder.).
make_unique_name
Sætter fejlnumret til en given værdi.
- protected function set_errno($no){
- $this->errno = $no;
- }
Metoden scope er sat til protected, linje 1, for at den kan blive kaldt af arvende klasser.
get_error_number
Returnerer det sidst satte fejlnummer til brugeren.
- public function get_error_number(){
- return $this->errno;
- }
get_error_message
Returnerer en tekstbesked baseret på det sidst sidst satte fejlnummer.
- public function get_error_message(){
- switch($this->errno){
- case 2: return 'The file type is not allowed';
- case 3: return 'This is not an uploaded file';
- case 4: return 'Could not move file to destination';
- case 11: return 'The file exceeds size ini directive';
- case 12: return 'The file exceeds size form directive';
- case 13: return 'file upload was only partial';
- case 14: return 'no file was attached';
- case 16: return 'no temporary directory for files';
- case 17: return 'can\'t write to disk';
- case 18: return 'an extension blocked upload';
- default: return 'This ('.$this->errno.') is not a known error id.';
- }
- }
Metoden består af en switch, linje 2, der tester på det satte fejlnummer. Hvis fejlnumret er et kendt et returneres en tekstbesked, men hvis fejlnumret er ukendt returneres en tekstbesked om dette. Da arvende klasser ikke kan ændre i en switch erklæring, forventes det at disse implementerer deres egen get_error_message metode med en switch erklæring over deres fejlbeskeder og denne switch erklæring kalder klassens parent::get_error_message() som default.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (2)
God og gennemtænkt artikel!
helt sikkert noget jeg vil få brug for på mit site...
tak!
helt sikkert noget jeg vil få brug for på mit site...
tak!
skrotbil
Du skal være
logget ind for at skrive en kommentar.