DbHelp.ru
Маленький Yii блог
Комментарии
Андрей: Добрый день, а что делать если таблица связочная с 2-мя ...
Гость: Шел 2014 год, пятый год от начала обещаний...
Гость: Ощущение, что из практиков здесь нет никого, все сразу ...
Slavik: Нигде не вижу ответа на такой вопрос Как сделать что-б...
Denis: Полностью рабочий код для Yii 1.1.15 можете найти на https://gith...



Сервер Ultima Online - Forest Wars (от создателя данного блога)

Как загружать файлы с помощью модели?

Рубрика: Перевод Cookbook

Оцените эту статью:

Рейтинг: 0.00 (0)
5 Апр. 2009
Опубликовать в Twitter Написать в Facebook Опубликовать в своем блоге livejournal.com

Yii Framework Blog img http://dbhelp.rucookbook Первым делом необходимо объявить переменную в моделе для хранения имени файла . Также стоит незабыть указать правило валидации (в rules) для нашего поля. Там вы можете задать расширения файлов которые могут быть загружены.

---

class Item extends CActiveRecord
{
    public $image;
    // ... other attributes
 
    public function rules()
    {
        return array(
            array('image', 'file', 'types'=>'jpg, gif, png'),
        );
    }
}

После этого в контроллере стоит обьявить экшинс который будет загружать форму и обрабатывать данные из неё.

class ItemController extends CController
{
    public function actionCreate()
    {
        $model=new Item;
        if(isset($_POST['Item']))
        {
            $model->attributes=$_POST['Item'];
            $model->image=CUploadedFile::getInstance($model,'image');
            if($model->save())
            {
                $model->image->saveAs('path/to/localFile');
                // redirect to success page
            }
        }
        $this->render('create', array('model'=>$model));
    }
}

И наконец, создание файла отображения и добавление в него элемента для загрузки файла.

<?php echo CHtml::form('','post',array('enctype'=>'multipart/form-data')); ?>
...
<?php echo CHtml::activeFileField($model, 'image'); ?>
...
</form>

Данная статья является мои переводом http://www.yiiframework.com/doc/cookbook/2/



Если хотите опубликовать этот материал у себя - пожалуйста, разместите ссылку на страницу откуда вы его взяли.
Другие yii статьи:

  1. Эта статья устарела т.к. была написана для yii версии 1.0.х; Если вы используете более новую версию - у вас могут ... "Урок2 : Первичная настройка"

  2. Давайте сегодня поговорим что же такое “контроллер” и для чего он используется в приложениях на базе MVC next В уроке ... "Шаг 5 : Контроллер"

  3. Не знаю почему, но многие разработчики с которыми я переписываюсь совершенно не верно решают проблема "пустых данных" в ... "Принтуем данные из attributes"

[guest] Гость

Было сказано: Суббота, 25 Апрель 2009

Одно не понятно почему CActiveRecord ? разве АР это не для базы данных?

[guest] Гость

Было сказано: Понедельник, 27 Апрель 2009

Предполагается что имя файла который мы загружаем или хотябы путь к нему будет хранится в базе данных. Следовательно за доставерность пришедших с формы данных отвечает модель, отсюда и AP :)

[guest] Константин

Было сказано: Вторник, 28 Апрель 2009

Какая разница - АР или FormModel, в данном случае иллюстрируется валидация поля типа файл и его удобная загрузка средствами Yii.

[adm] zolter

Было сказано: Вторник, 28 Апрель 2009

Да, Константин прав.
В данном случае показано как легко средствами фреймворка проводить и валидацию фаил полей с формы.

romanoza

Было сказано: Четверг, 14 Май 2009

а каким образом можно переименовать файл до save()? что бы сохранить и в базу записать под другим именем?

romanoza

Было сказано: Четверг, 14 Май 2009

сам и отвечаю :)
может быть криво, но сделал так:


$private $_image;

$this->_image=CUploadedFile::getInstance($user,'image');
if($this->_image->name)
$user->image=Gallery::nameImage($this->_image->extensionName);
else
$user->image = NULL;

if ($user->save(false)) {
if($this->_image->name) {
$this->_image->saveAs('images/userfiles/'.Yii::app()->user->id.'/'.$user->image);
}
$this->redirect($redirect);
}

[guest] Максим

Было сказано: Четверг, 14 Май 2009

Спасибо romanoza, хороший вариант!
Также спасибо автору статьи!

[guest] Гость

Было сказано: Суббота, 11 Июль 2009

работаю из-под винды...
выдает ошибку

move_uploaded_file(E:/mowes_portable/site/images/items) [<a href='function.move-uploaded-file'>function.move-uploaded-file</a>]: failed to open stream: Permission denied


что может быть???
папка существует - вставка пути в проводник перекидывает в эту папку

[adm] zolter

Было сказано: Воскресенье, 12 Июль 2009

Странно. Ругается на права доступа к папке. Но в винде у меня такой ошибки некогда не появлялось. Попробуйте удалить текущую папку и создать её по новой через проводник. Поместите в эту папку какойто файл и попробуйте получить к нему доступ через функцию http://ua2.php.net/manual/ru/function.is-writable.php

А какая винда? vista?

[guest] Гость

Было сказано: Суббота, 25 Июль 2009

при сохранении файлов с русскими буквами в названии, сохраняет какую-то ерунду... можно это как-то исправить?

[adm] zolter

Было сказано: Суббота, 25 Июль 2009

Скорее всего это проблемы самой ОС. При сохранении простой кодируйте название файла в md5 к примеру.

[guest] Гость

Было сказано: Суббота, 07 Ноябрь 2009

спасибо за перевод, одно только не ясно, чем отличаются данные метода
$model->save()
$model->image->saveAs()

в частности save() от saveAs()
каждая из них что желает?

вроде как я понял, метод saveAs() сохраняет файл в указанной директории, а вот в методе save() мы не указываем директорю, так смысл от ниё какой?

[adm] zolter

Было сказано: Суббота, 07 Ноябрь 2009

Метод $model->save() сохраняет аттрибуты модели $model в базу данных. При этом работу с самим прикрепленным файлом он не какую не выполняет. Как вы понимаете у нас модель знимается не только загрузкой файла, но и к примеру сохранением другой информации в туже таблицу. К примеру название файла и тп. Поэтому данный метод обновит именно таблицу в БД.

А метод $model->image->saveAs() проводит именно непосредственне сохранение файла на жесткий диск сервера. Без работы с базой данных.

[guest] Гость

Было сказано: Воскресенье, 08 Ноябрь 2009

zolter, спасибо огромное за разъяснение, теперь всё ясно)

[adm] zolter

Было сказано: Воскресенье, 08 Ноябрь 2009

Пожалуйста :)

itsme

Было сказано: Пятница, 04 Декабрь 2009

все понятно кроме одного
в какую таблицу (имя таблицы) модель сохраняется ?

[guest] zolter

Было сказано: Пятница, 04 Декабрь 2009

В модели должен быть метод tableName который указывает, с какой таблицей работает модель:

        public function tableName()
{
return 'art_galery'; // <-ваше имя
}

[guest] Гость

Было сказано: Среда, 27 Январь 2010

Народ, загружать то мы научились, а удалять как? не подскажет никто случайно?

[guest] Гость

Было сказано: Среда, 27 Январь 2010

Может unlink(имя файла)? Или Вы хотите как-то интересней?

[guest] Гость

Было сказано: Четверг, 28 Январь 2010

не мне любой:) главное чтобы удалял, спасибо

[guest] Гость

Было сказано: Вторник, 09 Февраль 2010

хм. у меня такая проблема:
форма с несколькими полями где текстовые значения, а также собственно возможность загрузки файлов в этой же форме.
как достать из формы файл и сохранить его? мне настойчиво пишет что форма пуста если я использую немного переделанный пример приведенный вами. если же я этот пример не использую то имя ффайла в БД сохраняется, а сам файл наверняка удаляется из временных файлов.
как его выловить из временных файлов и скопировать в нужную директорию?

[guest] zolter

Было сказано: Вторник, 09 Февраль 2010

http://ua.php.net/manual/en/function.move-uploaded-file.php

<?php
$uploads_dir = '/uploads';
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
}
?>

[guest] BOLVERIN

Было сказано: Четверг, 11 Февраль 2010

блииииин.. спасибо :) только что-то грузится никак не хочет - нету доступа к папке.

[guest] BOLVERIN

Было сказано: Четверг, 11 Февраль 2010

ужо разобрался абсолютный путь указать надо было

[guest] zolter

Было сказано: Четверг, 11 Февраль 2010

Пожалуйста :)

[guest] Гость

Было сказано: Воскресенье, 25 Апрель 2010

Пацики, чтобы переименовать файл до save() необязательно создавать instance CUploadedFile в $model, можно просто создать допольнительную переменную и генерировать имя уже в $model.


if(isset($_POST['Book'])) {
$model->attributes=$_POST['Book'];
$cover=CUploadedFile::getInstance($model,'cover');
if (isset($cover)) {
//генерация уникального имени файла
$uname=substr(md5(uniqid(rand(), true)), 0, rand(7, 13)).preg_replace('/(^.*)(\.)/','$2',$cover->name);
$model->cover = $uname;
}
if($model->save()) {
// сохранение в БД
if (isset($cover)) {
// сохранение на диск
$cover->saveAs($path.$uname);
$image = Yii::app()->image->load('files/images/'.$uname);
$image->resize(200,100,Image::WIDTH);
$image->save('files/images/thumbs/thumb_'.$uname);
}
$this->redirect(array('view','id'=>$model->id));
}

}

[guest] Joyce

Было сказано: Четверг, 26 Август 2010

В некоторых браузерах код не работает. Файлы просто не грузятся. Дело в том, что одни размещают данные в массив $_POST , а другие в $_FILES. Проверяю тупо print_r(). Кто- нибудь сталкивался с такой проблемой? Заранее пасибо.

[guest] Гость

Было сказано: Четверг, 26 Август 2010

Конкретно на Mac: Safari, Chrome - работает FF-не работает.

[guest] Joyce

Было сказано: Четверг, 26 Август 2010

Yii создаёт скрытые поля для передачи данных файла. Видимо это происходит на этапе submit с помощью JavaScript. Таким образом данные о файле (файлах) пихаются в $_POST. Так кривовато решается проблема с разными браузерами. А так как у меня форма загрузки - Widget, то JavaScript не работает корректно. Кто-нибудь разбирался с процессом?
Не будет ли лучше сделать разборку на сервере и выбирать корректный массив ($_FILES или $_POST соответсвенно).

[adm] zolter

Было сказано: Четверг, 26 Август 2010

Странно не сталкивался с тем что в $_POST кидало, а не в $_FILES.

[guest] Гость

Было сказано: Пятница, 27 Август 2010

To Zolter: Это потому, что не Widget. Написал свой обработчик submit - ActiveForm выкинул оставил CHtml - всё работает. Завтра сделаю зависимость парсинг массивов ($_POST & $_FILES) на сервере, чтобы не использовать JavaScript и дополнительные скрытые поля.

[guest] Гость

Было сказано: Пятница, 27 Август 2010

Согласен!

[guest] Гость

Было сказано: Пятница, 29 Апрель 2011

Никак не ролучается загрузить файл!
CUploadedFile::getInstance - возвращает NULL

[guest] Гость

Было сказано: Пятница, 06 Май 2011


$form=$this->beginWidget('CActiveForm', array(
'id'=>'otzyv-form',
'enableAjaxValidation'=>false,
'htmlOptions' => array('enctype'=>'multipart/form-data'),

[guest] Grigori

Было сказано: Четверг, 09 Июнь 2011

С этим алгоритмом появляется большая проблема, если аплоадится картинка, которую надо проверить на формат и размеры перед записью в базу.
Проверка данных - задача модели, выносить проверку в контроллер так же, как вызов image->saveAs - bad practice.

Лучше вынести вызов ->saveAs() в модель в метод beforeSave(), который вызываются после валидации данных.

Для проверки картинки я написал свой валидатор размеров картинки, он простой, выложу в extensions как руки дойдут.

[guest] Гость

Было сказано: Среда, 14 Декабрь 2011

Извиняюсь что занимаюсь некромантией, но не подскажет кто нибудь:
Как использовать правило для валидации файла если имя картинки должно записывается в другую таблицу (например в Item_Images)

[guest] Гость

Было сказано: Пятница, 06 Апрель 2012

спасибо!

[guest] Гость

Было сказано: Воскресенье, 01 Июль 2012

$model->image=CUploadedFile::getInstance($model,'image');

Если известно уже местоположение файла, как его засунуть за место image?

[guest] Гость

Было сказано: Вторник, 21 Август 2012

public function actionCreate(){

if(isset($_POST['News'])) {

$model->attributes=$_POST['News'];

$cover=CUploadedFile::getInstance($model,'cover');

if (isset($cover)) {

//генерация уникального имени файла

$uname=substr(md5(uniqid(rand(), true)), 0, rand(7, 13)).preg_replace('/(^.*)(\.)/','$2',$cover->name);

$model->cover = $uname;

}

if($model->save()) {

// сохранение в БД

if (isset($cover)) {

// сохранение на диск

$cover->saveAs($path.$uname);

$image = Yii::app()->image->load('images/'.$uname);

$image->resize(200,100,Image::WIDTH);

$image->save('images/thumbs/thumb_'.$uname);

}

#$this->redirect(array('view','id'=>$model->id));

}

$this->render('create', array('model'=>$model));

}
}


Вот сделал под себя. Почему пустая страница? Помогите.

[guest] Гость

Было сказано: Вторник, 25 Сентябрь 2012

Пример на основе этого же урока.
Мне всегда легче разобратся когда есть два примера, повторяющих то же самое с минимальными измениниями, поэтому ставлю свой баян (для бабушек, работающих с yii).
сначала
1. я создала таблицу в базе данных
2. с помощью gii создала model
3. с помощью gii создала CRUD

пример из этой статьи

class ItemController extends CController
{
public function actionCreate()
{
$model=new Item;
if(isset($_POST['Item']))
{
$model->attributes=$_POST['Item'];
$model->image=CUploadedFile::getInstance($model,'image');
if($model->save())
{
$model->image->saveAs('path/to/localFile');
// redirect to success page
}
}
$this->render('create', array('model'=>$model));
}
}


мои минимальные измениния в файле controllers/HividController.php


public function actionCreate()
{
$model=new Hivid;

// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);

if(isset($_POST['Hivid']))
{
$model->attributes=$_POST['Hivid'];
$model->pathVideo=CUploadedFile::getInstance($model,'pathVideo');


if($model->save())
$model->pathVideo->saveAs(Yii::app()->basePath . '/../images/' . $model->pathVideo);
$this->redirect(array('view','id'=>$model->id));


}

$this->render('create',array(
'model'=>$model,
));
}


мои минимальные изменения в файле models/Hivid.php

class Hivid extends CActiveRecord
{

public $pathVideo;
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('pathVideo', 'required'),
array('sport, postTitle', 'length', 'max'=>100),
array('pathVideo', 'length', 'max'=>150),
//array('pathVideo', 'file', 'types'=>'avi, wmv, mpg, mpeg, mov, rm, ram, swf, flv, mp4, txt, jpg, gif, png,'),
array('postCaption', 'safe'),
().
// Please remove those attributes that should not be searched.
array('id, sport, postTitle, postCaption, pathVideo', 'safe', 'on'=>'search'),



);
}

мои минимальные измениния в файле views/hivid/_form.php
<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'hivid-form',
'enableAjaxValidation'=>false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),

<div class="row">
<?php echo $form->labelEx($model,'pathVideo'); ?>

<?php echo $form->fileField($model,'pathVideo'); ?>
<?php echo $form->error($model,'pathVideo'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Upload' : 'Save'); ?>
</div>

<?php $this->endWidget(); ?>
)); ?>

[guest] Гость

Было сказано: Понедельник, 20 Январь 2014

не знаю у кого как а у меня все равно не грузится не в локалхост не в веб хостит (( что делать - не знаю

[guest] Гость

Было сказано: Четверг, 14 Август 2014

что это за 'path/to/localFile' ??? Слабо было описать ?
Я туда подставляю '/image/', '/image/'.$s, '/image/мойфайл' и нихнера не сохраняется постоянно выдает ошибки.

Блин столько народа парится над сохранением файла, неужели никто не может предложить один правильный шаблонный вариант ? Ведь задача тупая до ужаса, сохранить файл в папку. Тут никакого yii не надо, оно только мешает.

Оставить комментарий


Код:
Имя: