Yii загрузка файлов

по мотивам

создаем таблицу (я использую postgres)

CREATE TABLE techbase.item (
  id SERIAL,
  name TEXT NOT NULL,
  url TEXT,
  CONSTRAINT item_pkey PRIMARY KEY(id),
  CONSTRAINT item_url_key UNIQUE(url)
) 
WITH (oids = false);

COMMENT ON COLUMN techbase.item.id
IS 'ид';

COMMENT ON COLUMN techbase.item.name
IS 'имя';

COMMENT ON COLUMN techbase.item.url
IS 'Источник (URL без http://)';

создаем модель и круд

правим protected\models\Item.php чтобы получилось следующее

class Item extends CActiveRecord
{

    public $icon; // атрибут для хранения загружаемой картинки статьи
    public $del_img; // атрибут для удаления уже загруженной картинки

    /**
     * @return string the associated database table name
     */

    public function tableName()
    {
        return 'item';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('name', 'required'),
            array('url', 'safe'),
            array('del_img', 'boolean'),
            array('icon', 'file',
                'types' => 'doc,docx,xls,xlsx,odt,pdf',
                'maxSize' => 1024 * 1024 * 5, // 5 MB
                'allowEmpty' => 'true',
                'tooLarge' => 'Файл весит больше 5 MB. Пожалуйста, загрузите файл меньшего размера.',
            ),
            // The following rule is used by search().
            // @todo Please remove those attributes that should not be searched.
            array('id, name, url', 'safe', 'on' => 'search'),
        );
    }
    
    public function attributeLabels()
    {
        return array(
            'id' => 'ид',
            'name' => 'имя',
            'url' => 'Источник (URL без http://)',
            'icon' => 'Картинка к статье',
            'del_img' => 'Удалить картинку?',
        );
    }
в корне  создаем папку files

\views\item\_form.php добавляем

    <div class="row">
        <?php echo $form->labelEx($model, 'url'); ?>
        <?php
        //Если картинка для данного товара загружена, предложить её удалить, отметив чекбокс
        if (isset($model->url) && file_exists($_SERVER['DOCUMENT_ROOT'] .
                        Yii::app()->urlManager->baseUrl .
                        '/files/' . $model->url))
        {
            echo $form->checkBox($model, 'del_img', array('class' => 'span-1'));
            echo $form->labelEx($model, 'del_img', array('class' => 'span-2'));
        }
        ?> 
        <br />
        <?php
        //Поле загрузки файла
        echo CHtml::activeFileField($model, 'icon');
        ?>
        <?php echo $form->error($model, 'url'); ?>
    </div>

ну и поправим

    <?php
    $form = $this->beginWidget('CActiveForm', array(
        'id' => 'item-form',
        // Please note: When you enable ajax validation, make sure the corresponding
        // controller action is handling ajax validation correctly.
        // There is a call to performAjaxValidation() commented in generated controller code.
        // See class documentation of CActiveForm for details on this.
        'enableAjaxValidation' => false,
        'htmlOptions' => array('enctype' => 'multipart/form-data'),
    ));
    ?>

\controllers\ItemController.php

    public function actionCreate()
    {

        $model = new Item;

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

        if (isset($_POST['Item']))
        {
            //Полю icon присвоить значения поля формы icon
            $model->attributes = $_POST['Item'];
            $model->icon = CUploadedFile::getInstance($model, 'icon');
            if ($model->icon)
            {
                $sql = "   SELECT COALESCE(setval('techbase.item_id_seq', max(id)),nextval('techbase.item_id_seq'))  FROM techbase.item,
                    (SELECT 
                    nextval('techbase.item_id_seq')) as sel";
                $connection = Yii::app()->db;
                $id = $connection->createCommand($sql)->queryScalar() + 1;

                $sourcePath = pathinfo($model->icon->getName());
                $fileName = $id . '_doc.' . $sourcePath['extension'];
                $model->url = $fileName;
            }

            if ($model->save())
            {
                //Если поле загрузки файла не было пустым, то            
                if ($model->icon)
                {
                    //сохранить файл на сервере в каталог images/2011 под именем 
                    //month-day-alias.jpg
                    $file = $_SERVER['DOCUMENT_ROOT'] .
                            Yii::app()->urlManager->baseUrl .
                            '/files/' . $fileName;
                    $model->icon->saveAs($file);
                }
                $this->redirect(array('view', 'id' => $id));
            }
        }

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

    public function actionUpdate($id)
    {
        $model = $this->loadModel($id);

        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);
        if (isset($model->url))
        {
            $docname = $model->url;
        }

        if (isset($_POST['Item']))
        {
            $model->attributes = $_POST['Item'];
            $model->icon = CUploadedFile::getInstance($model, 'icon');
            if ($model->icon)
            {
                $sourcePath = pathinfo($model->icon->getName());
                $fileName = $model->id . '_doc.' . $sourcePath['extension'];
                $model->url = $fileName;
            }
            //Если отмечен чекбокс «удалить файл»            
            if ($model->del_img)
            {
                if (file_exists($_SERVER['DOCUMENT_ROOT'] .
                                Yii::app()->urlManager->baseUrl .
                                '/files/' . $model->url))
                {
                    //удаляем файл
                    unlink('./files/' . $model->url);
                    $model->url = NULL;
                }
            }
            if ($model->save())
            {
                //Если поле загрузки файла не было пустым, то            
                if ($model->icon)
                {
                    if (isset($model->url) && (file_exists($_SERVER['DOCUMENT_ROOT'] .
                                    Yii::app()->urlManager->baseUrl .
                                    '/files/' . $model->url)))
                        unlink('./files/' . $docname);
                    $file = './files/' . $fileName;
                    //сохранить файл на сервере под именем 
                    //month-day-alias.jpg Если файл с таким именем существует, он будет заменен.
                    $model->icon->saveAs($file);
                }
                $this->redirect(array('view', 'id' => $model->id));
            }
        }

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

    /**
     * Deletes a particular model.
     * If deletion is successful, the browser will be redirected to the 'admin' page.
     * @param integer $id the ID of the model to be deleted
     */
    public function actionDelete($id)
    {
        $model = $this->loadModel($id);
        if (isset($model->url) && (file_exists($_SERVER['DOCUMENT_ROOT'] .
                        Yii::app()->urlManager->baseUrl .
                        '/files/' . $model->url)))
            unlink('./files/' . $model->url);
        $this->loadModel($id)->delete();

        // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
        if (!isset($_GET['ajax']))
            $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
    }

Без скачивания тутор будет не полным.
добавим в \protected\controllers\ItemController.php

    public function actionGetFile($id)
    {

        // некоторая логика по обработке пути из url в путь до файла на сервере
        $currentFile = $_SERVER['DOCUMENT_ROOT'] .
                Yii::app()->urlManager->baseUrl .
                '/files/' . $id;

        if (is_file($currentFile))
        {
            header("Content-Type: application/octet-stream");
            header("Accept-Ranges: bytes");
            header("Content-Length: " . filesize($currentFile));
            header("Content-Disposition: attachment; filename=" . $id);
            readfile($currentFile);
        };
    }

не забудьте

    public function accessRules()
    {
        return array(
            array('allow', // allow all users to perform 'index' and 'view' actions
                'actions' => array('index', 'view', 'getfile'),
                'users' => array('*'),
            ),

\protected\views\item\admin.php

$this->widget('zii.widgets.grid.CGridView', array(
    'id' => 'item-grid',
    'dataProvider' => $model->search(),
    'filter' => $model,
    'columns' => array(
        'id',
        'name',
        //'url',
        array(
            'name' => 'url',
            'type' => 'raw',
            'value' => 'CHtml::link("файл", "getfile/id/".$data->url)'
        ),
        array(
            'class' => 'CButtonColumn',
        ),
    ),
));

protected\views\item\_view.php

    <b><?php echo CHtml::encode($data->getAttributeLabel('url')); ?>:</b> 
    <?php echo  CHtml::link("файл", "getfile/id/".$data->url); ?>
    <br />

\protected\views\item\view.php
$this->widget('zii.widgets.CDetailView', array(
    'data' => $model,
    'attributes' => array(
        'id',
        'name',
        'url' => array(
            'name' => 'url',
            'value' => CHtml::link("файл", "getfile/id/" . $data->url),
        ),
    ),
));

























Комментарии

Популярные сообщения из этого блога

Пишем логи на C# (.NET). Легкий способ.

Учебник yii2