如何在YII2 PHP Framework上使用CKEDITOR实现文件上传?

时间:2017-09-13 10:17:27

标签: yii yii2 ckeditor

我是YII2 PHP框架的新手。我想在TextArea中实现Ckeditor。我有了库,但尝试使用CKeidtor查找上传文件。我不知道如何在CkEditor中实现文件上传。 Library For CkEditor

2 个答案:

答案 0 :(得分:1)

如果您仍在寻找解决方案或其他人。 2amigos在Yii2中为ckeditor建立了一个惊人的Library。要使用图片上传选项实现它,您应该设置如下:

 <?= $form->field($model, 'yourParameter')
         ->widget(CKEditor::className(), 
            [
              'options' => [], 
              'preset' => 'custom',
              'clientOptions' => [
                  'extraPlugins' => '',
                  'height' => 500,

                  //Here you give the action who will handle the image upload 
                  'filebrowserUploadUrl' => '/site/ckeditor_image_upload',

                  'toolbarGroups' => [
                      ['name' => 'undo'],
                      ['name' => 'basicstyles', 'groups' => ['basicstyles', 'cleanup']],
                      ['name' => 'paragraph', 'groups' => ['list', 'indent', 'blocks', 'align', 'bidi' ]],
                      ['name' => 'styles'],
                      ['name' => 'links', 'groups' => ['links', 'insert']]
                  ]

              ]

            ]) 

?>

现在因为你必须自己构建图像上传处理程序,这里有一个如何做的例子。

public function actionCkeditor_image_upload()
{       
    $funcNum = $_REQUEST['CKEditorFuncNum'];

    if($_FILES['upload']) {

      if (($_FILES['upload'] == "none") OR (empty($_FILES['upload']['name']))) {
      $message = Yii::t('app', "Please Upload an image.");
      }

      else if ($_FILES['upload']["size"] == 0 OR $_FILES['upload']["size"] > 5*1024*1024)
      {
      $message = Yii::t('app', "The image should not exceed 5MB.");
      }

      else if ( ($_FILES['upload']["type"] != "image/jpg") 
                AND ($_FILES['upload']["type"] != "image/jpeg") 
                AND ($_FILES['upload']["type"] != "image/png"))
      {
      $message = Yii::t('app', "The image type should be JPG , JPEG Or PNG.");
      }

      else if (!is_uploaded_file($_FILES['upload']["tmp_name"])){

      $message = Yii::t('app', "Upload Error, Please try again.");
      }

      else {
        //you need this (use yii\db\Expression;) for RAND() method 
        $random = rand(0123456789, 9876543210);

        $extension = pathinfo($_FILES['upload']['name'], PATHINFO_EXTENSION);

        //Rename the image here the way you want
        $name = date("m-d-Y-h-i-s", time())."-".$random.'.'.$extension; 

        // Here is the folder where you will save the images
        $folder = 'uploads/ckeditor_images/';  

        $url = Yii::$app->urlManager->createAbsoluteUrl($folder.$name);

        move_uploaded_file( $_FILES['upload']['tmp_name'], $folder.$name );

      }

      echo '<script type="text/javascript">window.parent.CKEDITOR.tools.callFunction("'
           .$funcNum.'", "'.$url.'", "'.$message.'" );</script>';

    }


}

现在由于CSRF-Token问题,插件有时会出问题。要解决此问题,您只能通过以下操作停用CSRF令牌:

 public function beforeAction($action)
{            
    if ($action->id == 'ckeditor_image_upload') {
        $this->enableCsrfValidation = false;
    }

    return parent::beforeAction($action);
}

Image选项现在可以使用了。

答案 1 :(得分:0)

对于那些像我一样寻求通过CKEditor(基于弗朗西斯解决方案)上传文件的完整指南的人。

首先,您应该使用2amigos widget来简化生活。

在要包含CKEditor的视图中呈现该小部件:

<?= $form->field($model, 'YOUR_FIELD_NAME')->widget(CKEditor::className(), [
    'preset' => 'full',
    'clientOptions' => [
        'filebrowserUploadUrl' => '/CONTROLLER_NAME/upload',
        'filebrowserBrowseUrl' => '/CONTROLLER_NAME/browse'
    ]
]);
?>

在上面的代码中,我使用了完整的预设,您可以使用任何喜欢的预设(或使用'custom'值对其进行自定义)。

注意:您应该将控制器名称附加在url字符串中,以便可以同时使用它创建和更新操作


'filebrowserUploadUrl' => 'upload'

在这里您应该输入将处理文件上传的操作名称。弗朗西斯在例子方面做得很好,所以我只能说它应该以以下格式返回JSON:

//In case of success:
return [
                'fileName' => $NAME_OF_THE_FILE,
                'uploaded' => true,
                'url' => $URL_TO_SHOW_THE_FILE,
            ];
//In case of error:
return [
            'error' => [
                'message' => $MESSAGE_TEXT,
            ],
        ];

如果您的操作将返回除该JSON以外的任何内容-它会显示警告消息,显示“未定义”或“服务器响应不正确”消息。


filebrowserBrowseUrl' => 'browse'

如果您不想让用户浏览上传的文件-只需从小部件选项中删除该行即可。

在其他情况下,您应该向控制器添加actionBrowse方法,该方法将呈现页面以浏览和选择图像。

控制器方法:

public function actionBrowse(){
    //get function num to pass it to the view (need to be called to pass data of selected file to CKEditor)
    $CKEditorFuncNum = Yii::$app->request->get('CKEditorFuncNum');

    //get list of uploaded files 
    $files = yii\helpers\FileHelper::findFiles($PATH_TO_FOLDER);

    return $this->renderAjax('browse', [
        'funcNum' => $CKEditorFuncNum,
        'files' => $files,
    ]);
}

注意:该视图将作为模式对话框打开,因此我更喜欢使用renderAjax而不是render函数来避免渲染布局。但是如果您要使用资产捆绑包,我不建议您使用renderPartial

查看文件:

use yii\helpers\Html;

\backend\assets\AppAsset::register($this);

?>
<div class="container">

<h1><?= Html::encode(Yii::t('common', 'Choose any file')) ?></h1>

<?php if (!empty($files)): ?>
    <div class="row">
        <?php foreach ($files as $file):
            $url = "/$file"; ?>
        <div class="col-md-4 mb-2">
            <img 
                src="<?= $url ?>" 
                class="img-thumbnail" 
                style="cursor: pointer; margin-bottom: 2rem"
                onClick="selectImage(<?= $funcNum ?>, '<?= $url ?>')"
            />
        </div>
        <?php endforeach; ?>
    </div>
<?php endif; ?>
</div>
<script type="text/javascript">
    function selectImage(funcNum, url){
        window.opener.CKEDITOR.tools.callFunction(funcNum, url)
        window.close()
    }
</script>

selectImage函数将调用CKEditor函数将图像url传递到文件上传模式,然后关闭模式对话框。