後端DEMO:https://github.com/coderliguoqing/UeditorSpringbootphp
前端DEMO:https://github.com/coderliguoqing/ueditor-webhtml
預覽地址:https://coderliguoqing.github.io/ueditor-web/dist/#/ueditor前端
寫在最前面的話:鑑於近期不少的博友討論,說我按照文章的一步一步來,弄好以後,怎麼會提示後端配置項http錯誤,文件上傳會提示上傳錯誤。這裏提別申明一點,ueditor在前端配置好後,須要與後端部分配合進行,後端部分的項目代碼git地址:https://github.com/coderliguoqing/UeditorSpringboot,而後將配置ueditor.config.js 裏的serverUrl的前綴改陳你本身的後端訪問的請求路徑地址,文件上傳的後端部分,只提供了demo,具體對接文件服務器的部分須要本身修改完成。vue
首先,談下這篇文章中的先後端所涉及到的技術框架內容。java
雖然是後端的管理項目,但總體項目,是採用先後端分離的方式完成,這樣作的目的也是產品化的需求;webpack
前端,vue+vuex+vue router+webpack+elementUI的方案完成框架的搭建,其中用到了superUI來做爲後端登錄以後的主頁面框架,中間集成vue的大型單頁應用;git
後端,springboot+spring+springmvc+spring serurity+mybatis+maven+redis+dubbo程序員
+zookeeper的方式來構建項目框架和管理,提供給前端restful風格的接口。此處還提供app端、PC WEB端的接口。github
UEditor以前一直有在項目中使用,做爲國內開源的富文本編輯器,有百度的強大技術支持,總體來講是不錯的選擇,百度也提供了php、asp、.net、jsp的版本。原有的項目是採用總體式的開發方式,採用的是jsp的頁面開發技術,因此集成起來相對來講更加容易,只須要按照文檔的方式將前端集成進去,而後後端拿到源碼以後,針對文件上傳的類修改最終存儲的方法便可將文件等上傳到自己的服務器了。web
然而,因爲決定了作先後端分離的方式,必然就會有新的坑,特別是還選擇了新的技術vue.js+elementUI的這種方式。那麼也只能放手一搏,很少囉嗦,介紹完,立刻開始正事。
一、下載UEditor官網最新的jsp版本的包,下載完成解壓以後獲得一個ueditor1_4_3_3-utf8-jsp的文件夾,裏面包含的內容以下:
除了jsp的文件夾以外,其他的文件和文件夾複製到前端項目中的static用於存放靜態文件的目錄下,結構以下:
這裏特別說明jsp目錄下的資源爲什麼不放進來,由於咱們是vue搭建的項目,jsp頁面確定是不會放在前端的項目中的,包括config.json也放在後端用於解析,這裏後面會解釋這樣作的緣由。
二、前端將文件放進來以後,暫時先這樣,我們來整理後端的東西。這裏將jsp目錄下的lib目中的ueditor.jar文件中的全部類所有拿出來(具體方式本身決定,反編譯工具或者拿到源碼均可以),放到後端項目中,而後在control層新建一個UeditorController.java的類,以下:
1 /** 2 * 用於處理關於ueditor插件相關的請求 3 * @author Guoqing 4 * 5 */ 6 @RestController 7 @CrossOrigin 8 @RequestMapping("/sys/ueditor") 9 public class UeditorController extends BaseController { 10 11 @RequestMapping(value = "/exec") 12 @ResponseBody 13 public String exec(HttpServletRequest request) throws UnsupportedEncodingException{ 14 request.setCharacterEncoding("utf-8"); 15 String rootPath = request.getRealPath("/"); 16 return new ActionEnter( request, rootPath).exec(); 17 } 18 }
該類主要處理,ueditor與後端服務器的交互,經過action=''不一樣的類型來處理,其中action=config爲加載配置項,action=uploadImg 圖片上傳,在ActionEntor類中,你能夠根據不一樣的請求類型來處理;
處理當action=config時的狀況,保證前端的編輯器各項文件上傳功能,可以正常使用。
而後jsp目錄下的config.json文件放到java/main/resources目錄下,修改ConfigManager.java類,以下:
註釋掉原有的讀取配置文件的方式,添加新的讀取路徑,這樣確保ueditor在初始化可以正確的加載配置文件。此時,修改前端項目中ueditor.config.js中的serverUrl的值爲:
// 服務器統一請求接口路徑
, serverUrl: "http://localhost:8080/sys/ueditor/exec"
而,針對ActionEnter.java類中,以下代碼後的文件上傳的處理,請你們針對自身的上傳方式和文件服務器選擇適合本身的方式:
switch ( actionCode ) { //讀取配置文件時的請求處理 case ActionMap.CONFIG: return this.configManager.getAllConfig().toString(); //上傳圖片、視頻、文件時的處理 case ActionMap.UPLOAD_IMAGE: case ActionMap.UPLOAD_SCRAWL: case ActionMap.UPLOAD_VIDEO: case ActionMap.UPLOAD_FILE: conf = this.configManager.getConfig( actionCode ); state = new Uploader( request, conf, baseFileService ).doExec(); break; //抓取遠程圖片時的處理方式,此處也能夠關閉 //當從網頁上覆制內容到編輯器中,若是圖片與該域名不一樣源,則會自動抓到本地的服務器保存 case ActionMap.CATCH_IMAGE: conf = configManager.getConfig( actionCode ); String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) ); state = new ImageHunter( conf ).capture( list ); break; //上傳多文件時的文件在線管理 case ActionMap.LIST_IMAGE: case ActionMap.LIST_FILE: conf = configManager.getConfig( actionCode ); int start = this.getStartIndex(); state = new FileManager( conf ).listFile( start ); break; } return state.toJSONString();
接下來是前端的處理,介於你們的要求。做者將本來的demo進行了優化,將編輯器封裝成組件的方式,方便調用,代碼以下:
<template> <div> <script id="editor" type="text/plain" ></script> </div> </template> <script> import AppConfig from '@/config' import '../../../../../../static/ueditor/ueditor.config.js' import '../../../../../../static/ueditor/ueditor.all.js' import '../../../../../../static/ueditor/lang/zh-cn/zh-cn.js' export default { name: "UEditor", props: { id: { type: String }, config: { type: Object } }, data() { return { editor: null } }, mounted() { //初始化UE const _this = this; this.editor = UE.getEditor('editor',this.config); }, destoryed() { this.editor.destory(); }, methods:{ getUEContent: function(){ return this.editor.getContent(); } } } </script>
導出組件:
var UEditor = require('./src/ueditor.vue'); module.exports = { UEditor }
這裏之因此是用一個模態框的方式來加載編輯器,是由於會存在編輯器工具欄浮動的問題,若是有問題,請根據以下的配置來處理便可;
頁面調用:
<template> <div id="app" class="hello"> <el-button size="primary" type="info" icon="plus" @click="openWindow">打開窗口</el-button> <el-dialog title="新增菜單" size="small" v-model="addFormVisible" :close-on-click-modal="false"> <div> <el-button size="primary" type="info" icon="plus" @click="getContent">獲取內容</el-button> <UEditor :config=config ref="ueditor"></UEditor> </div> </el-dialog> </div> </template> <script> import {UEditor} from './ueditor/index.js' export default{ name: 'hello', components: {UEditor}, data(){ return { config: { /*//能夠在此處定義工具欄的內容 toolbars: [ ['fullscreen', 'source','|', 'undo', 'redo','|','bold', 'italic', 'underline', 'fontborder', 'strikethrough', '|','superscript','subscript','|', 'forecolor', 'backcolor','|', 'removeformat','|', 'insertorderedlist', 'insertunorderedlist', '|','selectall', 'cleardoc','fontfamily','fontsize','justifyleft','justifyright','justifycenter','justifyjustify','|', 'link','unlink'] ],*/ autoHeightEnabled: false, autoFloatEnabled: true, //是否工具欄可浮動 initialContent:'請輸入內容', //初始化編輯器的內容,也能夠經過textarea/script給值,看官網例子 autoClearinitialContent:true, //是否自動清除編輯器初始內容,注意:若是focus屬性設置爲true,這個也爲真,那麼編輯器一上來就會觸發致使初始化的內容看不到了 initialFrameWidth: null, initialFrameHeight: 450, BaseUrl: '', UEDITOR_HOME_URL: 'static/ueditor/' }, addFormVisible: false } }, methods: { openWindow: function(){ this.addFormVisible = true; }, //獲取文檔內容 getContent: function(){ let content = this.$refs.ueditor.getUEContent(); console.log(content); alert(content); } } } </script>
至此,大功告成,包括文件上傳下載等部分所有搞定,不過要聲明一點的是,當出現接口與頁面部署域名不一樣時,點擊選擇圖片上傳會出現iframe跨域的問題。
2017-09-08的更新,做者已經經過更改源碼的方式,處理了單圖選擇文件上傳存在跨域的問題,處理方式固然就是將原有的form.submit的表單上傳方式,更改成ajax的上傳方式;
ueditor.all.js 24503行的方法替換,源碼以下:
/** * 2017-09-07 改掉了ueditor源碼,將自己的單文件上傳的方法改成ajax上傳,主要目的是爲了解決跨域的問題 * @author Guoqing */ domUtils.on(input, 'change', function() { if(!input.value) return; var loadingId = 'loading_' + (+new Date()).toString(36); var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName')); var allowFiles = me.getOpt('imageAllowFiles'); me.focus(); me.execCommand('inserthtml', '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme +'/images/spacer.gif" title="' + (me.getLang('simpleupload.loading') || '') + '" >'); /!* 判斷後端配置是否沒有加載成功 *!/ if (!me.getOpt('imageActionName')) { errorHandler(me.getLang('autoupload.errorLoadConfig')); return; } // 判斷文件格式是否錯誤 var filename = input.value, fileext = filename ? filename.substr(filename.lastIndexOf('.')):''; if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) { showErrorLoader(me.getLang('simpleupload.exceedTypeError')); return; } var params = utils.serializeParam(me.queryCommandValue('serverparam')) || ''; var action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?' : '&') + params); var formData = new FormData(); formData.append("upfile", form[0].files[0] ); $.ajax({ url: action, type: 'POST', cache: false, data: formData, processData: false, contentType: false, success: function (data) { data = JSON.parse(data); var link, loader, body = (iframe.contentDocument || iframe.contentWindow.document).body, result = body.innerText || body.textContent || ''; link = me.options.imageUrlPrefix + data.url; if(data.state == 'SUCCESS' && data.url) { loader = me.document.getElementById(loadingId); loader.setAttribute('src', link); loader.setAttribute('_src', link); loader.setAttribute('title', data.title || ''); loader.setAttribute('alt', data.original || ''); loader.removeAttribute('id'); domUtils.removeClasses(loader, 'loadingclass'); } else { showErrorLoader && showErrorLoader(data.state); } form.reset(); } }); function showErrorLoader(title){ if(loadingId) { var loader = me.document.getElementById(loadingId); loader && domUtils.remove(loader); me.fireEvent('showmessage', { 'id': loadingId, 'content': title, 'type': 'error', 'timeout': 4000 }); } } });
好了,若是以上對你有幫助的話,請順手點個贊,謝謝各位大蝦們啦!
效果圖以下:
/************************華麗麗的分割線*************************/
2017-11-29 響應你們的要求,先後端項目都提供了源碼的demo 請上github上查看,如還有問題,請多多交流
各位若是還有問題的,那麼請入羣吧: qq 581036486 入羣密碼:88888888
https://github.com/coderliguoqing
歡迎圍觀、點贊!
我只是一個不想作程序員的好程序員。