upload behaviour

Written by: adziki

Date May 30, 2008

Upload behaviour jest pomocny przy wysyłaniu plików formularzem html. Kod razem z przykładem użycia można ściągnąć z naszego repozytorium svn.

Podstawowe możliwości

Jest to prosty mechanizm pozwalający na automatyczne zapisywanie plików wysłanych formularzem. Zakładamy, że mamy model Myfile, który łączy się z tabelą myfiles. W tabeli interesuje nas jedno pole myfile typu string (255). W widoku tworzymy prosty formularz który umożliwi wysłanie do interesującego nas pola plik, zamiast tekstu:

$form->create(Myfile,array('type'=>'file'));
$form->input(Myfile.myfile, array('type'=>file));
$form->end('Submit');

Do utworzenia pola uploadu plików można również skorzystać z uploadHelper

W kontrolerze nie musimy dodawac nic poza standardowym kodem który umożliwi zapisanie rekordu. Behaviour wykryje, ze dane pole zawiera plik i automatycznie go przetworzy.

W modelu wystarczy dopisać nastepujaca linie, zeby cieszyć się jego podstawowymi funkcjami.

var $actsAs = array('Upload');

Upload behaviour zapisuje pliki w katalogu APP/webroot/files/[nazwa modelu]. Nazwa pliku jest znormalizowaną nazwą pliku wysyłanego (zawiera tylko litery alfabetu łacińskiego i podkreślenia).

Jeśli nie korzystamy z walidacji, behaviour “testuje” każde pole typu string w modelu - czy nie wysłano za jego pomocą plików. Jeśli tak w polu zostaje umieszczona nazwa pliku a plik zostaje zapisany w docelowym katalogu.

Usuwanie plików

Jeśli nie korzystamy z uploadHelper, należy dodać do formularza pole:

$this->form->input('myfile_delete', array('type'=>'checkbox'));

Zaznaczając checkbox można w łatwy sposób usuwać pliki.

Dla zapewnienia spójności plików z powiązanymi rekordami w bazie danych pliki są również usuwane automatycznie:

  • przy usuwaniu rekordu,
  • oraz przy edycji rekordu połączonej z wysłaniem nowego pliku w miejsce poprzedniego.

Walidacja

Jeśli chcemy skorzystać z walidacji do modelu trzeba dołączyć konfigurację walidacji:

function __construct(){
parent::__construct();
$this->validate = array(
'myfile' => array(
array('rule'=>array('validateUpload'), 'on'=>'create',  'message'=>'', 'last'=>true, 'allowEmpty'=>false),
array('rule'=>array('validateUpload'), 'on'=>'update', 'message'=>'Nie wysłano', 'required'=>false),
array('rule'=>array('validateMime','image'), 'message'=>__("Plik musi być obrazkiem (gif, jpeg albo png)",true)),
),
);
}

Dodatkowo, żeby walidacja przebiegała bez problemów konieczne jest dodanie poniższego kodu do modelu:

function save(&$data){
if(parent::save($data)){
return true;
}
$data = $this->data;
return false;
}

Jak dotąd dostępne są dwie funkcje walidacji:

  • validateUpload - za jej pomocą można sprawdzić poprawność uploadu pliku
  • validateMime - można określić dozwolone typy plików

validateMime

W validateMime są trzy sposoby zdefiniowania zakresu dozwolonych plików:

  1. Predefiniowane ustawienie - jak narazie tylko ‘image’
    (odpowiada wyrażeniu regularnemu: '/^image\/(pjpeg|jpeg|jpg|png|gif)$/');
    użyte w powyższym przykładzie
  2. Tablica typów mime - np array('text/plain','text/css');
    (Nie może to być tablica wyrażeń regularnych)
  3. Dowolne wyrażenie regularne (Perl-Compatible)

upload Helper

Jest to rozszerzenie dla standardowego formHelper, można je pobrać w naszym repozytorium svn. uploadHelper dostarcza jak dotąd tylko jedną funkcję, bardzo prosta w użyciu, utrzymana w stylu form helpera:

echo $upload->input('myfile', array('delete'=>false, 'preview'=>array('rel'=>'lightbox')));

Standardowo funkcja input generuje link do pliku (jeśli już jakiś został przesłany), pole typu file do wysłania pliku formularzem i pole checkbox do usuwania pliku. Funkcja upload::input() umożliwia dostęp do parametrów linku podglądu, oraz pola do usuwania plików poprzez elementy tablicy opcji o kluczach ‘preview’ oraz ‘delete’. W powyższym przykładzie checkbox do usuwania plików został wyłączony, a do odnośnika został dodany atrybut rel=”lightbox”.

2 Responses to “upload behaviour”

  1. Maciej Grajcarek said:

    W jednym z projektów potrzebowałem sprawdzać wielkość uploadowanego pliku.
    Oto jak to osiągnąłem.
    Do pliku behaviora upload.php dołożyłem nową metodę:

    function validateFilesize(&$model, $variable, $params){

    $valid = true;
    if(!is_array($variable)){
    debug('UploadBehavior->validateMime()');
    return false;
    }

    foreach($variable AS $variableName => $variableValue){
    if ($variableValue['size'] > $params){
    $valid = false;
    }
    }

    if(!$valid){
    if(!empty($model->data[$model->name][$model->primaryKey])){
    //$tempModel = new $model->name();
    $data = $model->find(array($model->name.’.’.$model->primaryKey => $model->data[$model->name][$model->primaryKey]));
    $model->data[$model->name][$variableName] = $data[$model->name][$variableName];
    } else {
    $model->data[$model->name][$variableName] = ”;
    }
    return false;
    }

    return true;

    }


    Teraz w $validate oprócz rodzaju pliku, możemy również sprawdzić jego wielkość.

    'zdjecie1' => array(
    array('rule'=>array('validateUpload'), 'message'=>'Please, choose proper file to save', 'last'=>true),
    array('rule'=>array('validateMime','image'), 'message'=> "File must be an image (gif, jpeg, or png)",true),
    array('rule'=>array('validateFilesize','1024000'), 'message'=> "File size exceeded",true),
    ),

    Powyzszy przyklad pozwoli na upload tylko plików tych plików grafiki, których wielkość nie przekracza 1MB.

  2. Maciej Grajcarek said:

    Czasami potrzebna jest zmiana nazwy pliku i jego rozmiaru czy stopnia kompresji (np przy pomocy komponentu AydImage), a następnie zapis zmienionej nazwy do bazy.
    W takim przypadku konieczne jest odpięcie behaviora od pól z nazwami plików. Najprostszy sposób: unset($this->Offer->validate);. Oczywiście stracimy wtedy możliwość walidowania również innych pól modelu, ale w powyższym przypadku jest to dopuszczalne.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>