Niedawno miałem za zadanie napisać mały panel administracyjny dla pewnej szkoły. Panel ten miał posiadać m. in. możliwość uploadu plików na serwer. Po krótkim zastanowieniu przyszła mi myśl napisania klasy uploadera - narzędzia do uploadowania plików. Klasa była pisana na szybko w związku z tym chciałbym poddać ją do konsultacji z wami.
Zastanawiam się czego jej jeszcze brakuje, jakie posiada błędy, co można poprawić. Zaznaczam, że chciałbym jej używać także w przyszłych projektach.
Przede wszystkim chodzi o bezpieczeństwo i elastyczność.
Oto kod:
class CUploader { private $AllowedEx; // Dozwolone rozszerzenia private $path; private $MaxSize; // Maksymalny rozmiar pliku private $nFiles = 0; // Ilość plików w buforze //Modes private $mode_fip; // Tryb tworzący ścieżkę z katalogiem o nazwie pliku private $mode_fun; // Tryb bez buforowania private $mode_cd; // Tryb czyszczenia docelowego katalogu //Temp variables private $bTrueEx; // Zgodność rozszerzenia dodawanego pliku private $uploadedFiles; // Pliki wrzucone przez bufor na serwer public function __construct($sPath = UPLOAD_DIR, $Extensions = NULL, $nMaxSize = 1048576) { $this->path = $sPath; $this->MaxSize = $nMaxSize; $this->AllowedEx = $Extensions; } { $this->mode_fip = (bool) $config['MODE_FIP']; $this->mode_fun = (bool) $config['MODE_FUN']; $this->mode_cd = (bool) $config['MODE_CD']; return $this; } public function changeDir($sDir) { if($sDir !== NULL) { $this->path = $sDir; return $this; } else return false; } public function setAllowedEx($Extensions = NULL) { { $this->AllowedEx = $Extensions; return $this; } } public function clearBuffer() { { } return $this; } public function addFile($File) { if($this->checkEx($File['name']) === TRUE) // Sprawdzenie rozszerzenia { if($this->checkSize($File['size']) === TRUE) // Sprawdzenie rozmiaru { if($this->mode_fun === TRUE) // Tryb FILE_UP_NOW $this->upload($File); else { $this->aFILES[$this->nFiles] = $File; $this->nFiles++; } return true; } else return false; } else return false; } // Funkcja służąca upload'owi plików z bufora na serwer. Uchwyt FileHandle wykorzystywany w razie wyłączonego buforowania. // Domyślnie ustawiony na 0 (wyłączony). public function upload($FileHandle = 0) { if($FileHandle === 0 && $this->aFILES !== NULL) { { { if ($this->mode_fip === true) // Tryb FILE_IN_PATH if($this->mode_cd === true) // Tryb CLEAR_DIRECTION $this->clearDir($this->path); // W tym momencie $this->path wskazuje katalog docelowy $this->path = $this->path.$this->aFILES[$i]['name']; // Utworzenie pełnej ścieżki z nazwą pliku. { $this->uploadedFiles++; chmod($this->path, 0600); } } } return ($this->nFiles === $this->uploadedFiles ? true : false); } elseif ($FileHandle !== 0) { { if($this->mode_fip === true) // Tryb FILE_IN_PATH if($this->mode_cd === true) // Tryb CLEAR_DIRECTION $this->clearDir($this->path); // W tym momencie $this->path wskazuje katalog docelowy $this->path = $this->path.$this->$FileHandle['name']; { chmod($this->path, 0600); return true; } else return false; } else return false; } else return false; } private function checkEx ($sFileName) { if($this->AllowedEx !== NULL) { $this->bTrueEx = FALSE; { if($this->AllowedEx[$i] === pathinfo($sFileName, PATHINFO_EXTENSION)) // Jeżeli rozszerzenie pliku znajduje się w tablicy dostępnych rozszerzeń - TRUE $this->bTrueEx = TRUE; } return ($this->bTrueEx === TRUE ? TRUE : FALSE); } } private function checkSize($nValue) { return ($nValue <= $this->MaxSize ? TRUE : FALSE); } private function clearDir($sDir) { { { if($file!='.' && $file!='..') } } return true; } }
Jak widać klasa nie jest jeszcze ukończona i perfekcyjna, ale chciałbym się dowiedzieć czy w dobrym kierunku piszę ten kod.
Może pokrótce omówię jak to powinno działać.
Argumentami konstruktora są opcjonalnie ścieżka upload'u (domyślnie główny katalog), tablica zezwolonych rozszerzeń (możemy wybrać z dostępnych 'IMAGE', 'APPLICATION' itd., lub stworzyć własną $Ex = array('cokolwiek', 'cokolwiek2'); ) oraz maksymalny rozmiar przesyłanego pliku.
Cały upload przedstawię za pomocą schematu:
NOWY UPLOADER -> OKREŚLENIE GŁÓWNYCH PARAMETRÓW -> KONFIGURACJA TRYBÓW -> DODANIE PLIKU DO BUFORA (wielokrotne) -> UPLOAD PLIKÓW Z BUFORA
Za cel stawiałem sobie możliwość dodawania dowolnej ilości plików do bufora (tzw. multiupload).
Jeśli chodzi o tryby, jeszcze pozostawiłem ten moduł do dopracowania. Jak na razie dostępne są dwa tryby (nie wiem czy zbyt sensowne):
- MODE_FUN (FILE_UP_NOW) - tryb z wyłączonym buforowaniem. Pliki są od razu uploadowane z wywołaniem funkcji addFile();
- MODE_FIP (FILE_IN_PATH) - tryb z uploadowaniem pliku do katalogu o nazwie pliku, np. ./katalog/katalog2/podanie_11/podanie11.php
Z góry dzięki za uzasadnioną krytykę oraz uwagi.
Pozdrawiam
EDIT:
Uaktualniłem klasę, dodałem kilka poprawek oraz nowy mod MODE_CD (CLEAR_DIRECTION), który odpowiada za czyszczenie docelowego katalogu przed uploadowaniem plików. Planuję jeszcze dorobić obsługę wyjątków, a tym samym komunikatów i błędów. Już edytując ten post zauważyłem kilka niedopatrzeń, idę je poprawiać. ;-)