Загрузка картинок через CKEditor в Yii 2

В CKeditor есть возможность вставлять картинки в текст. Можно указать ссылку на картинку уже доступную из веб, а можно загрузить через загрузчик.

Автор . Дата: 07.03.2017

Внимание! Как подключить CKeditor к Yii2 читайте на этой странице!

В CKeditor есть возможность вставлять картинки в текст. Можно указать ссылку на картинку уже доступную из веб, а можно загрузить через загрузчик.

Для того, чтобы реализовать возможность загрузки картинок через CKEditor, нужно сначала его настроить. Настройка сводится к указанию адреса страницы, через которую будет происходить загрузка файлов.

[
	'preset' => 'custom',
	'clientOptions' => [
		'filebrowserImageUploadUrl' => '/files/upload'
	]
],

Этот код нужно поместить либо в настройки виджета при его вызове на странице:

<?= $form->field($model, 'text')->widget(CKEditor::className(), [
    'options' => ['rows' => 6],
    'preset' => 'custom',
    'clientOptions' => [
        'filebrowserImageUploadUrl' => '/files/upload'
    ],
]) ?>

либо в настройках контейнера зависимости в web.php:

<?php

$params = require(__DIR__ . '/params.php');

$config = [
    ...
    
    'container' => [
        'definitions' => [
            'dosamigos\ckeditor\CKEditor' => [
                'preset' => 'custom',
                'clientOptions' => [
                    'filebrowserImageUploadUrl' => '/files/upload'
                ]
            ]
        ],
    ],
    
    ...
];

Теперь мы можем реализовать контроллер, через который будут загружаться картинки на сервер:

<?php

namespace app\controllers;

use app\models\File;
use yii\web\Controller;
use yii\web\UploadedFile;

class FilesController extends Controller
{
    public function actionUpload($CKEditorFuncNum)
    {
        $file = UploadedFile::getInstanceByName('upload');

        if ($file)
        {
            $file_model = new File;

            if ($file_model->upload($file) && $file_model->save())
                return '<script type="text/javascript">window.parent.CKEDITOR.tools.callFunction("'.$CKEditorFuncNum.'", "'.$file_model->url.'", "");</script>';
            else
                return "Возникла ошибка при загрузке файла\n";
        }
        else
            return "Файл не загружен\n";
    }
}

CKEditor при загрузке файла ожидает, что сервер вернет определенный JavaScript код, который при выполнении вызовет Callback функцию и передаст в неё адрес загруженного файла на сервер. В нашем контролере используется модель File, опишем её:

<?php

namespace app\models;

use Yii;
use yii\helpers\BaseFileHelper;

/**
 * This is the model class for table "files".
 *
 * @property integer $id
 * @property string $dir
 * @property string $file_name
 * @property string $original_file_name
 * @property integer $type
 * @property string $url
 */
class File extends \yii\db\ActiveRecord
{
    const TYPE_IMAGE = 1;
    const TYPE_OTHER = 15;

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'files';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['type'], 'integer'],
            [['dir', 'file_name', 'original_file_name'], 'string', 'max' => 800],
        ];
    }

    public function upload($file)
    {
        if (strpos($file->type, "image") !== false)
        {
            $this->type = self::TYPE_IMAGE;

            $out_dir = '/uploads/images/'.substr(md5(time()), 0, 2).'/'.substr(md5(time()+1), 0, 2).'/';
        }
        else
        {
            $this->type = self::TYPE_OTHER;

            $out_dir = '/uploads/files/'.substr(md5(time()), 0, 2).'/'.substr(md5(time()+1), 0, 2).'/';
        }

        $out_file_name = md5(time()+2) . '.' . $file->extension;
        $out_file = $out_dir . $out_file_name;

        BaseFileHelper::createDirectory(Yii::getAlias("@webroot") . $out_dir);

        if ($file->saveAs(Yii::getAlias("@webroot") . $out_file))
        {
            $this->dir = $out_dir;
            $this->file_name = $out_file_name;
            $this->original_file_name = $file->baseName . '.' . $file->extension;

            return true;
        }
        else
            return false;
    }

    public function getUrl()
    {
        return $this->dir . '/' . $this->file_name;
    }

    public function beforeDelete()
    {
        $file_name = Yii::getAlias('@webroot') . $this->dir . $this->file_name;
        if (file_exists($file_name) && !is_dir($file_name))
            unlink($file_name);

        return parent::beforeDelete();
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'dir' => 'Dir',
            'file_name' => 'File Name',
            'original_file_name' => 'Original File Name',
            'type' => 'Type',
        ];
    }
}

Вот и все. Теперь ваше приложение сможет получать файлы через CKEditor, сохранять их, а так же удалять при удалении модели File. Не забудьте так же создать таблицу для хранения информации о файлах в вашей БД.


comments powered by HyperComments