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, $validate = true, $fieldList = array()){
if(parent::save($data, $validate, $fieldList)){
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”.

4 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.

  3. adziki said:

    Wniesiona poprawka do artykułu: zmieniony kod funkcji save, która powinna być dołączana do modelu.

    Powstało też ostatnio kilka nowych pomysłów, jak usprawnić działanie behaviora. Jak tylko uda się znaleźć trochę czasu, powstanie uaktualnienie.

  4. daniel said:

    hej,

    nie wiem czy widziales, ale ostatnio robilem update tego behaviora. dodalem mu pare rzeczy, ale tez nie mialem jeszcze kiedy o tym napisac.

    pozdr. daniel

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>