fileUpload - nowy projekt

Pod tą oryginalną nazwą kryje się zestaw klas przeznaczony do obsługi uploadu plików na serwer. Posiadają one jednak warte uwagi cechy, które zainteresują osoby o orientacji obiektowej.

Najnowsza wersja - fileUpload 1.2

Duży nacisk położyłem na na odseparowanie obsługi uploadu po stronie serwera, bo nie mogłem już patrzeć na źle zaprojektowane skrypty, których użycie wymaga za każdym razem osobnej implementacji całej klasy i oczyszczenia jej z naleciałości poprzedniego projektu.

Wiele przykładów w internecie sprowadza się do prostego skryptu.
1
2
3
4
5
6
7
8
9
10
<?php
if($_FILES['input_name']['tmp_name'])
{
  
$tmpFilename=$_FILES['input_name']['tmp_name'];
  
$filename=$_FILES['input_name']['name'];
  if(!
move_uploaded_file($tmpFilename'/moja/sciezka/'.$filename))
  {
    print 
"Nie udało się skopiować pliku... bla bla";
  }
}
?>


To oczywiście marna implementacja, pewnie trzeba by dodać sprawdzenie rozszerzenia, czy typu mime pliku. Problem w tym, że lwia część programistów wstawi po prostu kolejny if else do istniejącego kodu i efekt ich zadowoli. Mnie nie. Sięgnąłem do osławionych phpclasses.org i ściągnąłem pierwszy z brzegu projekt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class Foto_upload extends file_upload {
  
  var 
$x_size;
  var 
$y_size;
  var 
$x_max_size 300;
  var 
$y_max_size 200;
  var 
$x_max_thumb_size 110;
  var 
$y_max_thumb_size 88;
  var 
$thumb_folder;
  var 
$foto_folder;
  var 
$larger_dim;
  var 
$larger_curr_value;
  var 
$larger_dim_value;
  var 
$larger_dim_thumb_value;

//itd...
?>


Idealny wręcz przykład kodu, który nie dość, że jest w php4, to jest do odstrzału, bo ktoś pomyślał, że fajnie jest wyprawadzać pochodne dla określonych typów plików. image_upload, video_upload... imageANDvideo_upload i jeszcze dorzucił skalowanie obrazków, jak na promocji w supermarkecie.

Aby uniknąć takich pułapek postanowiłem rozdzielić funkcje pomocnicze, od tych, które są bezpośrednio związane z obsługą uploadu.
Pierwszą rzeczą, którą trzeba było ujednolicić, to tablica $_FILES, która ma zmienną strukturę. Inną, jeśli uploadujemy jeden plik i inną gdy wysyłamy więcej plików. Stąd już tylko krok do obiektu FILES. Taki obiekt ma wiele zalet, ale to głównych należy możliwość iterowania jego elementów, która z kolei jak po sznurku prowadzi nas do FilterItaratora.

Prosty FilterIterator, który przepuszcza tylko pliki o zadanym rozszerzeniu.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
class extensionUploadFilter extends FilterIterator
{
  
/**
   * Ustawia dozwolone rozszerzenia
   */
  
function __construct($obj$ext=array())
  {
    
$this->acceptedExtensions=$ext;
    
parent::__construct($obj);
  }

  
/**
   * Akceptuje, będź nie aktualny plik
   *
   * @return bool
   */
  
public function accept()
  {
    
$file=$this->current();
    if(!empty(
$this->acceptedExtensions))
    {
      
$extension=strrchr($file->getFilename(), '.')
      if(
in_array(, $this->acceptedExtensions))
      {
        return 
true;
      }
      else
      {
        
$file->markRefused(__CLASS__.' '.$extension);
        return 
false;
      }

    }
    return 
true;
  }
}
?>


Teraz dopiero można myśleć o obrazkach. (pociąłem trochę komentarze)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class imageUploadFilter extends FilterIterator
{
  protected 
$acceptedExtensions=array(
  
".jpg",
  
".png",
  
".gif",
  
".bmp"
  
);

  function 
__construct($obj)
  {
    
$ob=new extensionUploadFilter($obj$this->acceptedExtensions);
    
parent::__construct($ob);
  }
  
  public function 
accept()
  {
    return 
true;
  }
}
?>


Specjalnie nie rozszerzyłem klasy extensionUploadFilter, bo sprawdzenie, czy obrazek jest obrazkiem dokonujemy również na podstawie mime-type. Dlatego kompozycja sprawdza się w takim wypadku dużo lepiej od dziedziczenia. Wystarczy napisać klasę filtrującą typ mime, konstruktor wypsażyć w dodatkową linijke kodu.
1
2
3
4
5
6
7
8
9
<?php
  
function __construct($obj)
  {
    
$ob=new extensionUploadFilter($obj$this->acceptedExtensions);
    
//dodajemy
    
$ob=new mimetypeUploadFilter($ob$this->acceptedExtensions);
    
parent::__construct($ob);
  }
?>


Mój fileUpload posiada jeszcze wiele wad i wiele funkcji ne zostało zaimplementowanych, ale jego projekt zdaje się być dobry, zwłaszcza, że poważnie myślę o napisaniu fasady dla mojego frameworka, która dodatkowo umożliwi konfigurację działania uploadu w plikah ini, xml, czy yaml. Stawiam na częste wydawanie nowych wersji które pojawią się w tym katalogu

Komentarze

Info:

Nick:
Treść:

Yacho napisał(a)
imho to jest klasyczny przykład przerostu formy nad treścią - funkcjonalny bedzie tak naprawde tylko w tych projektach gdzie upload plikow stanowi znaczna czesc funkcjonalności.
Ale ostatecznie to i tak jest kwestia gustu.
menic napisał(a)
Dorzuc przyklad jakis jak to to dziala :)
cysiaczek napisał(a)
W pliku executeUpload.php jest przykład - w wersji 1.3.1. Są tam zakomentowane przykłady użycia z różnymi filtrami. W nowym roku dorzucę przykład z iframe+ajax i progressbarem. :)
Marcif napisał(a)
>W nowym roku dorzucę przykład z iframe+ajax i progressbarem. :)

Kiedy można się tego przykładu spodziewać?
cysiaczek napisał(a)
Nie potrafię powiedzieć, kiedy dokładnie - liczę, że jeszcze w styczniu, ale to zależy od tego, ile czasu znajdę :)
 
Symfony_button