百度的開源前端富文本編輯器Ueditor各種有着強大的功能,但是在實際項目中,往往不會把圖片直接上傳到後端服務器上,而是上傳到圖牀或者CDN上,那麼如何配置呢?
服務端代碼分析
在ueditor目錄的php目錄下有下面這些文件
其中controller.php 是一個控制器文件,裏面做了一個簡單的路由,可以看到有一個uploadimage 路由到了action_upload.php
switch ($action) {
case 'config':
$result = json_encode($CONFIG);
break;
/* 上傳圖片 */
case 'uploadimage':
/* 上傳塗鴉 */
case 'uploadscrawl':
/* 上傳視頻 */
case 'uploadvideo':
/* 上傳文件 */
case 'uploadfile':
$result = include("action_upload.php");
break;
/* 列出圖片 */
case 'listimage':
$result = include("action_list.php");
break;
/* 列出文件 */
case 'listfile':
$result = include("action_list.php");
break;
/* 抓取遠程文件 */
case 'catchimage':
$result = include("action_crawler.php");
break;
default:
$result = json_encode(array(
'state'=> '請求地址出錯'
));
break;
}
action_upload.php則實例化了Uploader.class.php的Uploader類,其中做的主要操作就是文件的移動操作
//創建目錄失敗
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
return;
} else if (!is_writeable($dirname)) {
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
return;
}
//移動文件
if (!(move_uploaded_file($file["tmp_name"], $this->filePath) && file_exists($this->filePath))) { //移動失敗
$this->stateInfo = $this->getStateInfo("ERROR_FILE_MOVE");
} else { //移動成功
$this->stateInfo = $this->stateMap[0];
}
所以通過分析這個過程,我們可以看到,ueditor是在前端上傳圖片時調用了/controller.php?action=uploadimage這個接口,而我們要做的就是將移動文件操作修改爲上傳到遠程圖牀或者CDN。
前端頁面修改
在ueditor.all.js中有一個方法getActionUrl返回了不同操作對應的接口地址
/**
* 根據action名稱獲取請求的路徑
* @method getActionUrl
* @remind 假如沒有設置serverUrl,會根據imageUrl設置默認的controller路徑
* @param { String } action action名稱
* @example
* ```javascript
* editor.getActionUrl('config'); //返回 "/ueditor/php/controller.php?action=config"
* editor.getActionUrl('image'); //返回 "/ueditor/php/controller.php?action=uplaodimage"
* editor.getActionUrl('scrawl'); //返回 "/ueditor/php/controller.php?action=uplaodscrawl"
* editor.getActionUrl('imageManager'); //返回 "/ueditor/php/controller.php?action=listimage"
* ```
*/
getActionUrl: function(action){
var actionName = this.getOpt(action) || action,
imageUrl = this.getOpt('imageUrl'),
serverUrl = this.getOpt('serverUrl');
if(!serverUrl && imageUrl) {
serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2');
}
if(serverUrl) {
serverUrl = serverUrl + (serverUrl.indexOf('?') == -1 ? '?':'&') + 'action=' + (actionName || '');
return utils.formatUrl(serverUrl);
} else {
return '';
}
}
那麼我們只要在頁面中重寫這個方法,讓它返回我們自己的上傳圖片接口地址就可以了
在編輯的頁面中加入以下代碼,其中當action等於uploadimage時調用我們自己的上傳接口,否則走原有的ueditor的接口
UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl;
UE.Editor.prototype.getActionUrl = function(action) {
if (action == 'uploadimage') {
return '/mycontroller/uploadimage';
} else {
return this._bkGetActionUrl.call(this, action);
}
}
同時在初始化Ueditor時將遠程抓取圖片的功能關閉,否則會在複製粘貼時自動講一個CDN上的圖片抓取保存到本地服務器
var ue = UE.getEditor('container',{
initialFrameHeight : 600,
initialFrameWidth : 1500,
catchRemoteImageEnable:false,
})
編寫後端接口
後端的PHP接口讀取上傳文件內容,然後調用圖牀或者CDN提供的上傳接口就可以了,注意這裏接口返回的數據格式應與Ueditor接口返回的相同,否則會報錯
<?php
$file = $_FILES['upfile'];
if ($_FILES["file"]["error"] == 0) {
//上傳文件到CDN
$res = array(
"state" => "", //上傳狀態,上傳成功時必須返回"SUCCESS"
"url" => "", //CDN地址
"title" => "", //新文件名
"original" => "", //原始文件名
"type" => "", //文件類型
"size" => "", //文件大小
);
echo json_encode($res);
}
這樣當使用Ueditor的上傳圖片功能時,就會把圖片上傳到圖牀或者CDN了。