springboot整合ueditor實現圖片上傳和文件上傳功能 寫在前面: 在閱讀本篇之前,請先按照我的這篇隨筆完成對ueditor的前期配置工作: springboot+layui 整合百度富文本編輯器ueditor入門使用教程(踩過的坑)https://www.cnblogs.com/rain ...
springboot整合ueditor實現圖片上傳和文件上傳功能
寫在前面:
在閱讀本篇之前,請先按照我的這篇隨筆完成對ueditor的前期配置工作:
springboot+layui 整合百度富文本編輯器ueditor入門使用教程(踩過的坑)https://www.cnblogs.com/rainbow-1/p/16365016.html
在完成對ueditor的基本配置後,圖片和文件的上傳主要是後端文件的配置,下麵簡單介紹一下步驟。
實現效果:
一、修改ueditor.config.js配置文件
首先第一步,要完成對配置文件的修改。預設的ueditor配置里,對配置文件的讀取是通過controller.jsp完成的,
因為springboot項目中,靜態jsp文件的訪問是不被允許的,所以我們需要重寫這段讀取配置文件信息的代碼,也就是通過寫自己的一個controller來完成這個過程,同時自定義圖片和文件上傳的位置等信息。
預設的controller.jsp位置如下圖:
這時候我們修改配置文件調用資源的介面名稱,打開ueditor.config.js,如下圖所示:
我通過server_url,拿到了項目的根路徑,然後拼接後面的/science-2.0/api/ueditor/config(項目名稱/路由名稱)拿到完整的訪問路徑。
二、編寫一個新的控制器(CommonController)
這個類就是我們第一步所修改的部分指向的這個控制器,它要完成對config.json文件(該文件位於jsp文件夾下,裡面是關於文件上傳的一些配置信息)的讀取,同時要完成對文件上傳的具體實現。
- 下麵我們先來看一下config.json文件(/jsp目錄下)
主要看一下圖片上傳配置的部分:
我們需要修改的部分如圖所示:basePath指的是你希望保存的磁碟位置(這個目錄最好事先存在),imageActionName是我們處理上傳圖片功能的那個路由,也就是在controller里是什麼,這裡就是什麼。
下麵的文件上傳部分類似:
- 下麵給出完成的controller代碼
import com.alibaba.fastjson.JSONException;
import com.baidu.ueditor.ActionEnter;
import com.google.common.base.Charsets;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.ClassUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.net.URL;
@RestController
@RequestMapping("/api/ueditor")
public class CommonController {
/**
* 判斷當前系統是否是Windows系統
* @return true:Windows系統,false:Linux系統
*/
private boolean isWindowsSystem(){
String property = System.getProperty("os.name").toLowerCase();
return property.contains("windows");
}
/**
* 獲取Ueditor的配置文件
* @return
*/
@RequestMapping("/config")
public void getConfigInfo(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException {
System.out.println("讀取ueditor配置文件!");
response.setContentType("application/json");
String rootPath = "";
// 判斷當前系統是否是Windows系統
if(isWindowsSystem()){
URL Path = ClassUtils.getDefaultClassLoader().getResource("");
String afterPath = URLDecoder.decode(Path.getPath(), "UTF-8");
rootPath = afterPath+ "static/UEditor/jsp";
} else {
// 將config.json文件放在jar包同級目錄下
rootPath = "/usr/local/zgxsoft/yunapp-backend/service";
}
System.out.println("rootPath:{}"+ rootPath);
try {
String exec = new ActionEnter(request, rootPath, "/config.json").exec();
PrintWriter writer = response.getWriter();
writer.write(exec);
writer.flush();
writer.close();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
/**
* Ueditor上傳文件
* 這裡以上傳圖片為例,圖片上傳後,imgPath將存儲圖片的保存路徑,返回到編輯器中做展示
* @param upfile
* @return
*/
@RequestMapping("uploadimage")
@ResponseBody
public Map<String,String> uploadImage(@RequestParam("upfile") MultipartFile upfile, HttpServletRequest request) throws IOException {
System.out.println("上傳圖片!");
//文件原名稱
String fileName = upfile.getOriginalFilename();
// 保存文件的新名字
String timeFileName = DateHelper.getDateToString(new Date());
String nowName = timeFileName+"_"+UUID.randomUUID()+fileName.substring(upfile.getOriginalFilename().lastIndexOf("."));
String uploadPath = "";
if(!upfile.isEmpty()){
String path = "D:/science-2.0/";
File f = new File(path);
if(!f.exists()){
// 第一次上傳文件新建文件夾
f.mkdirs();
}
uploadPath = path+nowName;
//按照路徑新建文件
File newFile = new File(uploadPath);
if(!newFile.exists()){
newFile.createNewFile();
}
//複製
FileCopyUtils.copy(upfile.getBytes(), newFile);
}
//返回結果信息(UEditor官方要求這個json格式)
Map<String,String> map = new HashMap<String,String >();
//是否上傳成功
map.put("state", "SUCCESS");
//現在文件名稱
map.put("title", nowName);
//文件原名稱
map.put("original", fileName);
//文件類型 .+尾碼名
map.put("type", fileName.substring(upfile.getOriginalFilename().lastIndexOf(".")));
//文件路徑
// map.put("url", uploadPath); // 瀏覽器不能直接訪問項目外目錄的圖片等文件,需要做虛擬路徑映射
map.put("url", "/PathImage/"+nowName); // 這個路徑的 /PathImage/ 是在配置類里指定的映射到本地的絕對路徑
//文件大小(位元組數)
map.put("size", upfile.getSize()+"");
return map;
}
@RequestMapping("uploadfile")
@ResponseBody
public Map<String,String> uploadfile(@RequestParam("upfile") MultipartFile upfile, HttpServletRequest request) throws IOException {
System.out.println("上傳文件!");
//文件原名稱
String fileName = upfile.getOriginalFilename();
// 保存文件的新名字
String timeFileName = DateHelper.getDateToString(new Date());
String nowName = timeFileName+"_"+UUID.randomUUID()+fileName.substring(upfile.getOriginalFilename().lastIndexOf("."));
//System.out.println("name---:"+nowName);
String uploadPath = "";
if(!upfile.isEmpty()){
String path = "D:/science-2.0/";
File f = new File(path);
if(!f.exists()){
// 第一次上傳文件新建文件夾
f.mkdirs();
}
uploadPath = path+nowName;
//按照路徑新建文件
File newFile = new File(uploadPath);
if(!newFile.exists()){
newFile.createNewFile();
}
//複製
FileCopyUtils.copy(upfile.getBytes(), newFile);
}
//返回結果信息(UEditor官方要求這個json格式)
Map<String,String> map = new HashMap<String,String >();
//是否上傳成功
map.put("state", "SUCCESS");
//現在文件名稱
map.put("title", nowName);
//文件原名稱
map.put("original", fileName);
//文件類型 .+尾碼名
map.put("type", fileName.substring(upfile.getOriginalFilename().lastIndexOf(".")));
//文件路徑
// map.put("url", uploadPath); // 瀏覽器不能直接訪問項目外目錄的圖片等文件,需要做虛擬路徑映射
map.put("url", "/PathFile/"+nowName); // 這個路徑的 /PathImage/ 是在配置類里指定的映射到本地的絕對路徑
//文件大小(位元組數)
map.put("size", upfile.getSize()+"");
return map;
}
}
這部分代碼裡面的內容簡單說一下:
- /api/ueditor/config,這個路徑是我們讀取config.json文件的地方,在這裡我們完成了對json文件的載入,這時候我們在點擊控制項上的上傳按鈕才可以被監聽到,那麼我們後面重寫的圖片和文件上傳的路徑才有了意義。
- /api/ueditor/uploadimage,這個路徑就是寫圖片上傳的部分,這部分代碼註釋比較詳細,讀者可以仔細閱讀。
- /api/ueditor/uploadfile,這個就是文件上傳的部分,和圖片類似(圖片實際上也是屬於文件範疇)
!!!!!!
劃重點:
下麵還需要完成一個重要的配置,我們目前完成的只是對文件的上傳存儲到磁碟的功能,但是我們還有一件事也很重要,那就是回顯,所謂回顯,就是把圖片和文件等對前端提供展示。那麼這部分要怎麼寫呢,其實道理很簡單,就是對本地磁碟的文件提供一個訪問的路徑就可以了。
我們回到最開始的話題,我們現在做的事情其實是放棄了控制項原有的controller,而自己寫了一個新的,這是因為springboot框架的訪問限制,那麼圖片和文件的回顯也就需要我們自己寫,不可以直接用config.json中的預設配置,因為那裡其實已經不能用了,我們要重寫就得重寫得徹徹底底。
預設是這樣的:
"imageUrlPrefix":"", /* 圖片訪問路徑首碼 */ "imagePathFormat": "/document/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */ /* {filename} 會替換成原文件名,配置這項需要註意中文亂碼問題 */ /* {rand:6} 會替換成隨機數,後面的數字是隨機數的位數 */ /* {time} 會替換成時間戳 */ /* {yyyy} 會替換成四位年份 */ /* {yy} 會替換成兩位年份 */ /* {mm} 會替換成兩位月份 */ /* {dd} 會替換成兩位日期 */ /* {hh} 會替換成兩位小時 */ /* {ii} 會替換成兩位分鐘 */ /* {ss} 會替換成兩位秒 */ /* 非法字元 \ : * ? " < > | */ /* 具請體看線上文檔: fex.baidu.com/ueditor/#use-format_upload_filename */
ueditor為我們提供了重寫之後需要給伺服器返回數據的格式:
{
"state": "SUCCESS",
"url": "upload/demo.jpg",
"title": "demo.jpg",
"original": "demo.jpg"
}
//這是官網提供的格式,我們還可以再加一些,比如上面的controller是這麼寫的:
//返回結果信息(UEditor官方要求這個json格式)
Map<String,String> map = new HashMap<String,String >();
//是否上傳成功
map.put("state", "SUCCESS");
//現在文件名稱
map.put("title", nowName);
//文件原名稱
map.put("original", fileName);
//文件類型 .+尾碼名
map.put("type", fileName.substring(upfile.getOriginalFilename().lastIndexOf(".")));
//文件路徑
// map.put("url", uploadPath); // 瀏覽器不能直接訪問項目外目錄的圖片等文件,需要做虛擬路徑映射
map.put("url", "/PathFile/"+nowName); // 這個路徑的 /PathImage/ 是在配置類里指定的映射到本地的絕對路徑
//文件大小(位元組數)
map.put("size", upfile.getSize()+"");
註意看map.put("url", "/PathFile/"+nowName);這段代碼
這段代碼完成的就是對應本地文件路徑的伺服器訪問路徑,所以我們需要再寫一個映射器文件完成對這個路徑的映射關係。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MyWebAppConfiguration extends WebMvcConfigurerAdapter {
/**
* Spring Boot中有預設的靜態資源訪問路徑,瀏覽器也不允許訪問項目目錄外的資源文件
* 添加一些虛擬路徑的映射
* 設置靜態資源路徑和上傳文件的路徑
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// /** 表示該目錄下所有文件
registry.addResourceHandler("/PathImage/**").addResourceLocations("file:/D:/science-2.0/");
registry.addResourceHandler("/PathFile/**").addResourceLocations("file:/D:/science-2.0/");
super.addResourceHandlers(registry);
}
}
其中由於文件名的日期尾碼是根據當前系統時間生成的,所以又封裝了一個日期類,代碼如下:
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateHelper {
public static String getDateToString(Date time) {
SimpleDateFormat formatter;
formatter = new SimpleDateFormat("yyyyMMddHHmmss");
String Time = formatter.format(time);
return Time;
}
}
小結一下
這裡我們主要在寫後端的代碼,我們一共需要三個類:一個是主控制器,一個是映射關係類,還有一個是日期處理類(這三個文件放一起就行)。註意裡面的一些關鍵路徑,和config.json里的路徑是一一對應的,一旦寫錯伺服器是無法訪問到的。還有映射關係類里的路徑也需要寫正確,否則伺服器只能完成對文件的上傳而無法完成對文件的回顯。
附ueditor.config.js
/**
* ueditor完整配置項
* 可以在這裡配置整個編輯器的特性
*/
/**************************提示********************************
* 所有被註釋的配置項均為UEditor預設值。
* 修改預設配置請首先確保已經完全明確該參數的真實用途。
* 主要有兩種修改方案,一種是取消此處註釋,然後修改成對應參數;另一種是在實例化編輯器時傳入對應參數。
* 當升級編輯器時,可直接使用舊版配置文件替換新版配置文件,不用擔心舊版配置文件中因缺少新功能所需的參數而導致腳本報錯。
**************************提示********************************/
(function () {
/**
* 編輯器資源文件根路徑。它所表示的含義是:以編輯器實例化頁面為當前路徑,指向編輯器資源文件(即dialog等文件夾)的路徑。
* 鑒於很多同學在使用編輯器的時候出現的種種路徑問題,此處強烈建議大家使用"相對於網站根目錄的相對路徑"進行配置。
* "相對於網站根目錄的相對路徑"也就是以斜杠開頭的形如"/myProject/ueditor/"這樣的路徑。
* 如果站點中有多個不在同一層級的頁面需要實例化編輯器,且引用了同一UEditor的時候,此處的URL可能不適用於每個頁面的編輯器。
* 因此,UEditor提供了針對不同頁面的編輯器可單獨配置的根路徑,具體來說,在需要實例化編輯器的頁面最頂部寫上如下代碼即可。
* 當然,需要令此處的URL等於對應的配置。
* window.UEDITOR_HOME_URL = "/xxxx/xxxx/";
*/
window.UEDITOR_HOME_URL = "/UEditor/";
var server_url = window.location.protocol+"//"+window.location.hostname+":"+window.location.port;
//alert("rul"+server_url);
/**
* 配置項主體。註意,此處所有涉及到路徑的配置別遺漏URL變數。
*/
var ser_url=server_url+"/api/ueditor/config";
var ip=window.location.hostname;
if(ip=="10.1.10.148"){
window.UEDITOR_HOME_URL = "/science-2.0/UEditor/";
ser_url= server_url+"/science-2.0/api/ueditor/config";
}
var URL = window.UEDITOR_HOME_URL || getUEBasePath();
window.UEDITOR_CONFIG = {
//為編輯器實例添加一個路徑,這個不能被註釋
UEDITOR_HOME_URL: URL
// 伺服器統一請求介面路徑
, serverUrl: ser_url
//工具欄上的所有的功能按鈕和下拉框,可以在new編輯器的實例時選擇自己需要的重新定義
, toolbars: [[
'undo', 'redo', '|', 'bold', 'italic',
'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript',
'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain',
'|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist',
'selectall', 'cleardoc', '|', 'rowspacingtop', 'rowspacingbottom', 'lineheight',
'|', 'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|', 'directionalityltr',
'directionalityrtl', 'indent', '|', 'justifyleft', 'justifycenter', 'justifyright',
'justifyjustify', '|', 'touppercase', 'tolowercase', '|','link', 'unlink', 'anchor',
'|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|', 'simpleupload',
'insertimage', 'emotion', 'scrawl', 'insertvideo', 'music', 'attachment', 'map',
'pagebreak', 'template','|','horizontal', 'date', 'time', 'spechars', '|',
'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow',
'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells',
'splittorows', 'splittocols', 'charts', '|', 'preview', 'searchreplace'
]]
//當滑鼠放在工具欄上時顯示的tooltip提示,留空支持自動多語言配置,否則以配置值為準
//,labelMap:{
// 'anchor':'', 'undo':''
//}
//語言配置項,預設是zh-cn。有需要的話也可以使用如下這樣的方式來自動多語言切換,當然,前提條件是lang文件夾下存在對應的語言文件:
//lang值也可以通過自動獲取 (navigator.language||navigator.browserLanguage ||navigator.userLanguage).toLowerCase()
//,lang:"zh-cn"
//,langPath:URL +"lang/"
//主題配置項,預設是default。有需要的話也可以使用如下這樣的方式來自動多主題切換,當然,前提條件是themes文件夾下存在對應的主題文件:
//現有如下皮膚:default
//,theme:'default'
//,themePath:URL +"themes/"
//,zIndex : 900 //編輯器層級的基數,預設是900
//針對getAllHtml方法,會在對應的head標簽中增加該編碼設置。
//,charset:"utf-8"
//若實例化編輯器的頁面手動修改的domain,此處需要設置為true
//,customDomain:false
//常用配置項目
//,isShow : true //預設顯示編輯器
//,textarea:'editorValue' // 提交表單時,伺服器獲取編輯器提交內容的所用的參數,多實例時可以給容器name屬性,會將name給定的值最為每個實例的鍵值,不用每次實例化的時候都設置這個值
//,initialContent:'歡迎使用ueditor!' //初始化編輯器的內容,也可以通過textarea/script給值,看官網例子
//,autoClearinitialContent:true //是否自動清除編輯器初始內容,註意:如果focus屬性設置為true,這個也為真,那麼編輯器一上來就會觸發導致初始化的內容看不到了
//,focus:false //初始化時,是否讓編輯器獲得焦點true或false
//如果自定義,最好給p標簽如下的行高,要不輸入中文時,會有跳動感
//,initialStyle:'p{line-height:1em}'//編輯器層級的基數,可以用來改變字體等
//,iframeCssUrl: URL + '/themes/iframe.css' //給編輯區域的iframe引入一個css文件
//indentValue
//首行縮進距離,預設是2em
//,indentValue:'2em'
//,initialFrameWidth:1000 //初始化編輯器寬度,預設1000
//,initialFrameHeight:320 //初始化編輯器高度,預設320
//,readonly : false //編輯器初始化結束後,編輯區域是否是只讀的,預設是false
//,autoClearEmptyNode : true //getContent時,是否刪除空的inlineElement節點(包括嵌套的情況)
//啟用自動保存
//,enableAutoSave: true
//自動保存間隔時間, 單位ms
//,saveInterval: 500
//,fullscreen : false //是否開啟初始化時即全屏,預設關閉
//,imagePopup:true //圖片操作的浮層開關,預設打開
//,autoSyncData:true //自動同步編輯器要提交的數據
//,emotionLocalization:false //是否開啟表情本地化,預設關閉。若要開啟請確保emotion文件夾下包含官網提供的images表情文件夾
//粘貼只保留標簽,去除標簽所有屬性
//,retainOnlyLabelPasted: false
//,pasteplain:false //是否預設為純文本粘貼。false為不使用純文本粘貼,true為使用純文本粘貼
//純文本粘貼模式下的過濾規則
//'filterTxtRules' : function(){
// function transP(node){
// node.tagName = 'p';
// node.setStyle();
// }
// return {
// //直接刪除及其位元組點內容
// '-' : 'script style object iframe embed input select',
// 'p': {$:{}},
// 'br':{$:{}},
// 'div':{'$':{}},
// 'li':{'$':{}},
// 'caption':transP,
// 'th':transP,
// 'tr':transP,
// 'h1':transP,'h2':transP,'h3':transP,'h4':transP,'h5':transP,'h6':transP,
// 'td':function(node){
// //沒有內容的td直接刪掉
// var txt = !!node.innerText();
// if(txt){
// node.parentNode.insertAfter(UE.uNode.createText(' '),node);
// }
// node.parentNode.removeChild(node,node.innerText())
// }
// }
//}()
//,allHtmlEnabled:false //提交到後臺的數據是否包含整個html字元串
//insertorderedlist
//有序列表的下拉配置,值留空時支持多語言自動識別,若配置值,則以此值為準
//,'insertorderedlist':{
// //自定的樣式
// 'num':'1,2,3...',
// 'num1':'1),2),3)...',
// 'num2':'(1),(2),(3)...',
// 'cn':'一,二,三....',
// 'cn1':'一),二),三)....',
// 'cn2':'(一),(二),(三)....',
// //系統自帶
// 'decimal' : '' , //'1,2,3...'
// 'lower-alpha' : '' , // 'a,b,c...'
// 'lower-roman' : '' , //'i,ii,iii...'
// 'upper-alpha' : '' , lang //'A,B,C'
// 'upper-roman' : '' //'I,II,III...'
//}
//insertunorderedlist
//無序列表的下拉配置,值留空時支持多語言自動識別,若配置值,則以此值為準
//,insertunorderedlist : { //自定的樣式
// 'dash' :'— 破折號', //-破折號
// 'dot':' 。 小圓圈', //系統自帶
// 'circle' : '', // '○ 小圓圈'
// 'disc' : '', // '● 小圓點'
// 'square' : '' //'■ 小方塊'
//}
//,listDefaultPaddingLeft : '30'//預設的左邊縮進的基數倍
//,listiconpath : 'http://bs.baidu.com/listicon/'//自定義標號的路徑
//,maxListLevel : 3 //限制可以tab的級數, 設置-1為不限制
//,autoTransWordToList:false //禁止word中粘貼進來的列表自動變成列表標簽
//fontfamily
//字體設置 label留空支持多語言自動切換,若配置,則以配置值為準
,'fontfamily':[
{ label:'',name:'songti',val:'宋體,SimSun'},
{ label: '', name: 'SimSun', val: '仿宋,SimSun' },
{ label:'',name:'FangSong_GB2312',val:'仿宋_GB2312 ,FangSong_GB2312'},
{ label:'',name:'kaiti',val:'楷體,楷體_GB2312, SimKai'},
{ label:'',name:'yahei',val:'微軟雅黑,Microsoft YaHei'},
{ label:'',name:'heiti',val:'黑體, SimHei'},
{ label:'',name:'lishu',val:'隸書, SimLi'},
{ label:'',name:'andaleMono',val:'andale mono'},
{ label:'',name:'arial',val:'arial, helvetica,sans-serif'},
{ label:'',name:'arialBlack',val:'arial black,avant garde'},
{ label:'',name:'comicSansMs',val:'comic sans ms'},
{ label:'',name:'impact',val:'impact,chicago'},
{ label:'',name:'timesNewRoman',val:'times new roman'}
]
//fontsize
//字型大小
//,'fontsize':[10, 11, 12, 14, 16, 18, 20, 24, 36]
//paragraph
//段落格式 值留空時支持多語言自動識別,若配置,則以配置值為準
//,'paragraph':{'p':'', 'h1':'', 'h2':'', 'h3':'', 'h4':'', 'h5':'', 'h6':''}
//rowspacingtop
//段間距 值和顯示的名字相同
//,'rowspacingtop':['5', '10', '15', '20', '25']
//rowspacingBottom
//段間距 值和顯示的名字相同
//,'rowspacingbottom':['5', '10', '15', '20', '25']
//lineheight
//行內間距 值和顯示的名字相同
//,'lineheight':['1', '1.5','1.75','2', '3', '4', '5']
//customstyle
//自定義樣式,不支持國際化,此處配置值即可最後顯示值
//block的元素是依據設置段落的邏輯設置的,inline的元素依據BIU的邏輯設置
//儘量使用一些常用的標簽
//參數說明
//tag 使用的標簽名字
//label 顯示的名字也是用來標識不同類型的標識符,註意這個值每個要不同,
//style 添加的樣式
//每一個對象就是一個自定義的樣式
//,'customstyle':[
// {tag:'h1', name:'tc', label:'', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'},
// {tag:'h1', name:'tl',label:'', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;margin:0 0 10px 0;'},
// {tag:'span',name:'im', label:'', style:'font-style:italic;font-weight:bold'},
// {tag:'span',name:'hi', label:'', style:'font-style:italic;font-weight:bold;color:rgb(51, 153, 204)'}
//]
//打開右鍵菜單功能
//,enableContextMenu: true
//右鍵菜單的內容,可以參考plugins/contextmenu.js裡邊的預設菜單的例子,label留空支持國際化,否則以此配置為準
//,contextMenu:[
// {
// label:'', //顯示的名稱
// cmdName:'selectall',//執行的command命令,當點擊這個右鍵菜單時
// //exec可選,有了exec就會在點擊時執行這個function,優先順序高於cmdName
// exec:function () {
// //this是當前編輯器的實例
// //this.ui._dialogs['inserttableDialog'].open();
// }
// }
//]
//快捷菜單
//,shortcutMenu:["fontfamily", "fontsize", "bold", "italic", "underline", "forecolor", "backcolor", "insertorderedlist", "insertunorderedlist"]
//elementPathEnabled
//是否啟用元素路徑,預設是顯示
//,elementPathEnabled : true
//wordCount
//,wordCount:true //是否開啟字數統計
//,maximumWords:10000 //允許的最大字元數
//字數統計提示,{#count}代表當前字數,{#leave}代表還可以輸入多少字元數,留空支持多語言自動切換,否則按此配置顯示
//,wordCountMsg:'' //當前已輸入 {#count} 個字元,您還可以輸入{#leave} 個字元
//超出字數限制提示 留空支持多語言自動切換,否則按此配置顯示
//,wordOverFlowMsg:'' //<span style="color:red;">你輸入的字元個數已經超出最大允許值,伺服器可能會拒絕保存!</span>
//tab
//點擊tab鍵時移動的距離,tabSize倍數,tabNode什麼字元做為單位
//,tabSize:4
//,tabNode:' '
//removeFormat
//清除格式時可以刪除的標簽和屬性
//removeForamtTags標簽
//,removeFormatTags:'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var'
//removeFormatAttributes屬性
//,removeFormatAttributes:'class,style,lang,width,height,align,hspace,valign'
//undo
//可以最多回退的次數,預設20
//,maxUndoCount:20
//當輸入的字元數超過該值時,保存一次現場
//,maxInputCount:1
//autoHeightEnabled
// 是否自動長高,預設true
//,autoHeightEnabled:true
//scaleEnabled
//是否可以拉伸長高,預設true(當開啟時,自動長高失效)
//,scaleEnabled:false
//,minFrameWidth:800 //編輯器拖動時最小寬度,預設800
//,minFrameHeight:220 //編輯器拖動時最小高度,預設220
//autoFloatEnabled
//是否保持toolbar的位置不動,預設true
//,autoFloatEnabled:true
//浮動時工具欄距離瀏覽器頂部的高度,用於某些具有固定頭部的頁面
//,topOffset:30
//編輯器底部距離工具欄高度(如果參數大於等於編輯器高度,則設置無效)
//,toolbarTopOffset:400
//設置遠程圖片是否抓取到本地保存
//,catchRemoteImageEnable: true //設置是否抓取遠程圖片
//pageBreakTag
//分頁標識符,預設是_ueditor_page_break_tag_
//,pageBreakTag:'_ueditor_page_break_tag_'
//autotypeset
//自動排版參數
//,autotypeset: {
// mergeEmptyline: true, //合併空行
// removeClass: true, //去掉冗餘的class
// removeEmptyline: false, //去掉空行
// textAlign:"left", //段落的排版方式,可以是 left,right,center,justify 去掉這個屬性表示不執行排版
// imageBlockLine: 'center', //圖片的浮動方式,獨占一行劇中,左右浮動,預設: center,left,right,none 去掉這個屬性表示不執行排版
// pasteFilter: false, //根據規則過濾沒事粘貼進來的內容
// clearFontSize: false, //去掉所有的內嵌字型大小,使用編輯器預設的字型大小
// clearFontFamily: false, //去掉所有的內嵌字體,使用編輯器預設的字體
// removeEmptyNode: false, // 去掉空節點
// //可以去掉的標簽
// removeTagNames: {標簽名字:1},
// indent: false, // 行首縮進
// indentValue : '2em', //行首縮進的大小
// bdc2sb: false,
// tobdc: false
//}
//tableDragable
//表格是否可以拖拽
//,tableDragable: true
//sourceEditor
//源碼的查看方式,codemirror 是代碼高亮,textarea是文本框,預設是codemirror
//註意預設codemirror只能在ie8+和非ie中使用
//,sourceEditor:"codemirror"
//如果sourceEditor是codemirror,還用配置一下兩個參數
//codeMirrorJsUrl js載入的路徑,預設是 URL + "third-party/codemirror/codemirror.js"
//,codeMirrorJsUrl:URL + "third-party/codemirror/codemirror.js"
//codeMirrorCssUrl css載入的路徑,預設是 URL + "third-party/codemirror/codemirror.css"
//,codeMirrorCssUrl:URL + "third-party/codemirror/codemirror.css"
//編輯器初始化完成後是否進入源碼模式,預設為否。
//,sourceEditorFirst:false
//iframeUrlMap
//dialog內容的路徑 ~會被替換成URL,垓屬性一旦打開,將覆蓋所有的dialog的預設路徑
//,iframeUrlMap:{
// 'anchor':'~/dialogs/anchor/anchor.html',
//}
//allowLinkProtocol 允許的鏈接地址,有這些首碼的鏈接地址不會自動添加http
//, allowLinkProtocols: ['http:', 'https:', '#', '/', 'ftp:', 'mailto:', 'tel:', 'git:', 'svn:']
//webAppKey 百度應用的APIkey,每個站長必須首先去百度官網註冊一個key後方能正常使用app功能,註冊介紹,http://app.baidu.com/static/cms/getapikey.html
//, webAppKey: ""
//預設過濾規則相關配置項目
//,disabledTableInTable:true //禁止表格嵌套
//,allowDivTransToP:true //允許進入編輯器的div標簽自動變成p標簽
//,rgb2Hex:true //預設產出的數據中的color自動從rgb格式變成16進位格式
// xss 過濾是否開啟,inserthtml等操作
,xssFilterRules: true
//input xss過濾
,inputXssFilter: true
//output xss過濾
,outputXssFilter: true
// xss過濾白名單 名單來源: https://raw.githubusercontent.com/leizongmin/js-xss/master/lib/default.js
,whitList: {
iframe: ['frameborder','border','marginwidth','marginheight','width','height','src','id'],//宋雨佳增加這一行
a: ['target', 'href', 'title', 'class', 'style'],
abbr: ['title', 'class', 'style'],
address: ['class', 'style'],
area: ['shape', 'coords', 'href', 'alt'],
article: [],
aside: [],
audio: ['autoplay', 'controls', 'loop', 'preload', 'src', 'class', 'style'],
b: ['class', 'style'],
bdi: ['dir'],
bdo: ['dir'],
big: [],
blockquote: ['cite', 'class', 'style'],
br: [],
caption: ['class', 'style'],
center: [],
cite: [],
code: ['class', 'style'],
col: ['align', 'valign', 'span', 'width', 'class', 'style'],
colgroup: ['align', 'valign', 'span', 'width', 'class', 'style'],
dd: ['class', 'style'],
del: ['datetime'],
details: ['open'],
div: ['class', 'style'],
dl: ['class', 'style'],
dt: ['class', 'style'],
em: ['class', 'style'],
font: ['color', 'size', 'face'],
footer: [],
h1: ['class', 'style'],
h2: ['class', 'style'],
h3: ['class', 'style'],
h4: ['class', 'style'],
h5: ['class', 'style'],
h6: ['class', 'style'],
header: [],
hr: [],
i: ['class', 'style'],
img: ['src', 'alt', 'title', 'width', 'height', 'id', '_src', 'loadingclass', 'class', 'data-latex'],
ins: ['datetime'],
li: ['class', 'style'],
mark: [],
nav: [],
ol: ['class', 'style'],
p: ['class', 'style'],
pre: ['class', 'style'],
s: [],
section:[],
small: [],
span: ['class', 'style'],
sub: ['class', 'style'],
sup: ['class', 'style'],
strong: ['class', 'style'],
table: ['width', 'border', 'align', 'valign', 'class', 'style'],
tbody: ['align', 'valign', 'class', 'style'],
td: ['width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'],
tfoot: ['align', 'valign', 'class', 'style'],
th: ['width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'],
thead: ['align', 'valign', 'class', 'style'],
tr: ['rowspan', 'align', 'valign', 'class', 'style'],
tt: [],
u: [],
ul: ['class', 'style'],
video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width', 'class', 'style']
}
};
function getUEBasePath(docUrl, confUrl) {
return getBasePath(docUrl || self.document.URL || self.location.href, confUrl || getConfigFilePath());
}
function getConfigFilePath() {
var configPath = document.getElementsByTagName('script');
return configPath[ configPath.length - 1 ].src;
}
function getBasePath(docUrl, confUrl) {
var basePath = confUrl;
if (/^(\/|\\\\)/.test(confUrl)) {
basePath = /^.+?\w(\/|\\\\)/.exec(docUrl)[0] + confUrl.replace(/^(\/|\\\\)/, '');
} else if (!/^[a-z]+:/i.test(confUrl)) {
docUrl = docUrl.split("#")[0].split("?")[0].replace(/[^\\\/]+$/, '');
basePath = docUrl + "" + confUrl;
}
return optimizationPath(basePath);
}
function optimizationPath(path) {
var protocol = /^[a-z]+:\/\//.exec(path)[ 0 ],
tmp = null,
res = [];
path = path.replace(protocol, "").split("?")[0].split("#")[0];
path = path.replace(/\\/g, '/').split(/\//);
path[ path.length - 1 ] = "";
while (path.length) {
if (( tmp = path.shift() ) === "..") {
res.pop();
} else if (tmp !== ".") {
res.push(tmp);
}
}
return protocol + res.join("/");
}
window.UE = {
getUEBasePath: getUEBasePath
};
})();
附config.json
/* 前後端通信相關的配置,註釋只允許使用多行方式 */
{
"basePath": "D:/scinece-2.0",
/* 上傳圖片配置項 */
"imageActionName": "uploadimage", /* 執行上傳圖片的action名稱 */
"imageFieldName": "upfile", /* 提交的圖片表單名稱 */
"imageMaxSize": 2048000, /* 上傳大小限制,單位B */
"imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上傳圖片格式顯示 */
"imageCompressEnable": true, /* 是否壓縮圖片,預設是true */
"imageCompressBorder": 1600, /* 圖片壓縮最長邊限制 */
"imageInsertAlign": "none", /* 插入的圖片浮動方式 */
"imageUrlPrefix":"", /* 圖片訪問路徑首碼 */
"imagePathFormat": "/document/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
/* {filename} 會替換成原文件名,配置這項需要註意中文亂碼問題 */
/* {rand:6} 會替換成隨機數,後面的數字是隨機數的位數 */
/* {time} 會替換成時間戳 */
/* {yyyy} 會替換成四位年份 */
/* {yy} 會替換成兩位年份 */
/* {mm} 會替換成兩位月份 */
/* {dd} 會替換成兩位日期 */
/* {hh} 會替換成兩位小時 */
/* {ii} 會替換成兩位分鐘 */
/* {ss} 會替換成兩位秒 */
/* 非法字元 \ : * ? " < > | */
/* 具請體看線上文檔: fex.baidu.com/ueditor/#use-format_upload_filename */
/* 塗鴉圖片上傳配置項 */
"scrawlActionName": "uploadscrawl", /* 執行上傳塗鴉的action名稱 */
"scrawlFieldName": "upfile", /* 提交的圖片表單名稱 */
"scrawlPathFormat": "/document/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"scrawlMaxSize": 2048000, /* 上傳大小限制,單位B */
"scrawlUrlPrefix":"", /* 圖片訪問路徑首碼 */
"scrawlInsertAlign": "none",
/* 截圖工具上傳 */
"snapscreenActionName": "uploadimage", /* 執行上傳截圖的action名稱 */
"snapscreenPathFormat": "/document/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"snapscreenUrlPrefix":"", /* 圖片訪問路徑首碼 */
"snapscreenInsertAlign": "none", /* 插入的圖片浮動方式 */
/* 抓取遠程圖片配置 */
"catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
"catcherActionName": "catchimage", /* 執行抓取遠程圖片的action名稱 */
"catcherFieldName": "source", /* 提交的圖片列表表單名稱 */
"catcherPathFormat": "/document/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"catcherUrlPrefix":"", /* 圖片訪問路徑首碼 */
"catcherMaxSize": 2048000, /* 上傳大小限制,單位B */
"catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取圖片格式顯示 */
/* 上傳視頻配置 */
"videoActionName": "uploadvideo", /* 執行上傳視頻的action名稱 */
"videoFieldName": "upfile", /* 提交的視頻表單名稱 */
"videoPathFormat": "/document/ueditor/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"videoUrlPrefix": "", /* 視頻訪問路徑首碼 */
"videoMaxSize": 102400000, /* 上傳大小限制,單位B,預設100MB */
"videoAllowFiles": [
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上傳視頻格式顯示 */
/* 上傳文件配置 */
"fileActionName": "uploadfile", /* controller里,執行上傳視頻的action名稱 */
"fileFieldName": "upfile", /* 提交的文件表單名稱 */
"filePathFormat": "/document/ueditor/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"fileUrlPrefix":"", /* 文件訪問路徑首碼 */
"fileMaxSize": 307200000, /* 上傳大小限制,單位B,預設50MB */
"fileAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
], /* 上傳文件格式顯示 */
/* 列出指定目錄下的圖片 */
"imageManagerActionName": "listimage", /* 執行圖片管理的action名稱 */
"imageManagerListPath": "/document/ueditor/image/", /* 指定要列出圖片的目錄 */
"imageManagerListSize": 20, /* 每次列出文件數量 */
"imageManagerUrlPrefix":"", /* 圖片訪問路徑首碼 */
"imageManagerInsertAlign": "none", /* 插入的圖片浮動方式 */
"imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件類型 */
/* 列出指定目錄下的文件 */
"fileManagerActionName": "listfile", /* 執行文件管理的action名稱 */
"fileManagerListPath": "/document/ueditor/file/", /* 指定要列出文件的目錄 */
"fileManagerUrlPrefix":"", /* 文件訪問路徑首碼 */
"fileManagerListSize": 20, /* 每次列出文件數量 */
"fileManagerAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
] /* 列出的文件類型 */
}
註意點 1 :如果你是按照我的上一篇隨筆完成的對ueditor的初始配置,那麼在你引入ueditor控制項的那個html文件里,一定存在這麼一段代碼:
<script type="text/javascript">
window.UEDITOR_HOME_URL = "/UEditor/";
</script>
這次在ueditor.config.js文件中,我指定了這個路徑,所以在頁面里的這個聲明就可以去掉了。而且我留著這裡是存在問題的,當然我不太確定是不是這裡導致的問題,如果大家配置完沒有問題,那這裡保留著也可以。
註意點 2 :這裡面有幾個路徑需要再提醒一下
在CommonController中: @RequestMapping("uploadimage")和 @RequestMapping("uploadfile") 需要和 config.json中的imageActionName一一對應。
config.json中:"basePath": "D:/scinece-2.0" 需要是你保存在磁碟的路徑,當然這裡好像不改也行,因為這裡被新寫的controller覆蓋了,可以嘗試不改看看有沒有問題,博主保險起見就一起改了。
CommonController 中的 map.put("url", "/PathFile/"+nowName);需要和映射器類的registry.addResourceHandler("/PathImage/**").addResourceLocations("file:/D:/science-2.0/"); 一一對應
CommonController 中的 rootPath = afterPath+ "static/UEditor/jsp";是相對於項目的classpath的路徑
對於SpringBoot項目來說,classpath
指的是src.main.java和src.main.resources
路徑以及第三方jar包的根路徑,存放在這兩個路徑下的文件,都可以通過classpath
作為相對路徑來引用;
因為在maven項目打包之後,會將項目變成如下圖所示的路徑,也就是說 /java 和 /resources 這兩個文件夾所在的路徑會消失,springboot項目會直接識別這兩個文件夾裡面的內容,****所以我們寫路徑的時候就直接可以從 resources 目錄的下一級開始,比如從/static或者 /template等等開始。
分享完畢,有不准確的地方大家交流指正,希望對大家有幫助!
好看請贊,養成習慣!
本文來自博客園,作者:靠譜楊,轉載請註明原文鏈接:https://www.cnblogs.com/rainbow-1/p/16383695.html