SpringBoot+Thymeleaf整合UEditor

1.下載UEditor

UEditor - 下載,將最新版本1.4.3.3的完整源碼和Jsp版本UTF-8版本下載下來並解壓。
下載UEditor

2.配置pom.xml

項目中配置UEditor的源碼需要的jar包

<dependency>
	<groupId>org.json</groupId>
	<artifactId>json</artifactId>
	<version>20180813</version>
</dependency>
<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.4</version>
</dependency>
<dependency>
	<groupId>commons-codec</groupId>
	<artifactId>commons-codec</artifactId>
	<version>1.11</version>
</dependency>

3.導入UEditor源碼及資源文件

3.1導入源碼文件

將解壓的完整源碼包下的jsp->src目錄下的源碼拷貝到項目對應包目錄下
導入UEditor源碼

3.2導入資源文件

將解壓的utf8-jsp版本目錄下的除jsp目錄和index.html文件,其餘文件全部導入到resources/static目錄下新建的ueditors文件夾中(注:帶有s的ueditors文件夾,後續會有說明)。
將目錄下的index.html文件拷貝到templates目錄下的ueditor文件夾下,根目錄下jsp目錄中的config.json拷貝到resources根路徑下。
UEditor靜態資源路徑
修改index.html資源引用路徑

<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>完整demo</title>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <script type="text/javascript" charset="utf-8" th:src="@{/ueditors/ueditor.config.js}"></script>
    <script type="text/javascript" charset="utf-8" th:src="@{/ueditors/ueditor.all.js}"> </script>
    <!--建議手動加在語言,避免在ie下有時因爲加載語言失敗導致編輯器加載失敗-->
    <!--這裏加載的語言文件會覆蓋你在配置項目裏添加的語言類型,比如你在配置項目裏配置的是英文,這裏加載的中文,那最後就是中文-->
    <script type="text/javascript" charset="utf-8" th:src="@{/ueditors/lang/zh-cn/zh-cn.js}"></script>

    <style type="text/css">
        div{
            width:100%;
        }
    </style>
</head>

4.自定義Controller訪問index.html頁面

package com.solang.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/ueditor")
public class UEditorController {

    @RequestMapping("/index")
    public String showUeditorPage() {
        return "ueditor/index";
    }
	
}	

5.運行項目並訪問路徑

由於application.properties配置了項目訪問路徑前綴

server.servlet.context-path=/ue

訪問http://localhost:8080/ue/ueditor/index,跳轉到如下界面說明源碼已拷貝成功
顯示完整demo
此時點擊多圖上傳,發現上傳圖片功能不能用
多圖上傳不能正常使用

6.編寫加載後端配置項的代碼

依據utf8-jsp版本目錄下jsp文件夾裏的controller.jsp,編寫加載後端配置項的代碼。

①application.properties文件配置UEditor上傳圖片視頻等存放路徑。

# UEditor上傳路徑地址
web.upload-path=E:/upload/

注:E:後面跟一個/

②在自定義Controller中繼續編寫代碼

package com.solang.controller;

import com.solang.ueditor.ActionEnter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Controller
@RequestMapping("/ueditor")
public class UEditorController {

    @Value("${web.upload-path}")
    private String uploadPath;

    @RequestMapping("/index")
    private String showUeditorPage(){
        return "ueditor/index";
    }

    @RequestMapping(value="/config")
    public void config(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("application/json");
        String rootPath = uploadPath;
        try {
            String exec = new ActionEnter(request, rootPath).exec();
            PrintWriter writer = response.getWriter();
            writer.write(exec);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
}

注:此處rootPath是做成可配置的,因爲查看UEditor的源碼,發現上傳圖片視頻等其實是上傳到rootPath目錄下的,不用像其它博客寫的那樣單獨定義一個上傳的參數。

③加載config.json文件,修改ConfigManage類的getConfigPath()方法

private String getConfigPath () {
		//return this.parentPath + File.separator + ConfigManager.configFileName;
		try {
			//獲取classpath下的config.json路徑
			return this.getClass().getClassLoader().getResource("config.json").toURI().getPath();
		} catch (URISyntaxException e) {
			return null;
		}
	}

此處需要先轉爲URI再getPath(),否則如果路徑帶空格或者帶中文則無法讀取到文件。

7.配置ueditor.config.js

   /**
    * 編輯器資源文件根路徑。它所表示的含義是:以編輯器實例化頁面爲當前路徑,指向編輯器資源文件(即dialog等文件夾)的路徑。
    * 鑑於很多同學在使用編輯器的時候出現的種種路徑問題,此處強烈建議大家使用"相對於網站根目錄的相對路徑"進行配置。
    * "相對於網站根目錄的相對路徑"也就是以斜槓開頭的形如"/myProject/ueditor/"這樣的路徑。
    * 如果站點中有多個不在同一層級的頁面需要實例化編輯器,且引用了同一UEditor的時候,此處的URL可能不適用於每個頁面的編輯器。
    * 因此,UEditor提供了針對不同頁面的編輯器可單獨配置的根路徑,具體來說,在需要實例化編輯器的頁面最頂部寫上如下代碼即可。當然,需要令此處的URL等於對應的配置。
    * window.UEDITOR_HOME_URL = "/xxxx/xxxx/";
    */
   var URL = window.UEDITOR_HOME_URL || getUEBasePath();

   /**
    * 配置項主體。注意,此處所有涉及到路徑的配置別遺漏URL變量。
    */
   window.UEDITOR_CONFIG = {

       //爲編輯器實例添加一個路徑,這個不能被註釋
       UEDITOR_HOME_URL: URL

      // 服務器統一請求接口路徑
       , serverUrl: URL + "jsp/controller.jsp"

根據提示推薦使用相對於網站根目錄的相對路徑的形式,本博客也會使用這種形式。

此處有必要先說明下URL的取值問題以及UEDITOR_HOME_URL和serverUrl的作用。

如果window.UEDITOR_HOME_URL未在頁面上定義或者取值爲空,那麼URL的值取的是getUEBasePath()方法,而這個方法返回的是UEditor的靜態資源存放的地址,例如本博客中URL獲取的地址就是:http://localhost:8080/ue/ueditors/

UEDITOR_HOME_URL地址其實就是UEditor靜態資源文件存放的地址,如果存放靜態資源文件的文件夾不是ueditors而是aaa,那麼地址就是http://localhost:8080/ue/aaa/。綜上所述,其實這個地址可以不用改

serverUrl是服務器統一請求接口路徑,其實就是Controller裏寫的加載config.json配置項的請求接口路徑,要改的也是這個serverUrl地址。

修改index.html頁面,在引入ueditor.config.js之前配置要獲取的項目路徑

<!DOCTYPE>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>完整demo</title>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <script type="text/javascript">
        var ctxPath= "[[${#httpServletRequest.getContextPath()}]]";
        window.CTX = ctxPath;
    </script>
    <script type="text/javascript" charset="utf-8" th:src="@{/ueditors/ueditor.config.js}"></script>
    <script type="text/javascript" charset="utf-8" th:src="@{/ueditors/ueditor.all.js}"> </script>
    <!--建議手動加在語言,避免在ie下有時因爲加載語言失敗導致編輯器加載失敗-->
    <!--這裏加載的語言文件會覆蓋你在配置項目裏添加的語言類型,比如你在配置項目裏配置的是英文,這裏加載的中文,那最後就是中文-->
    <script type="text/javascript" charset="utf-8" th:src="@{/ueditors/lang/zh-cn/zh-cn.js}"></script>

    <style type="text/css">
        div{
            width:100%;
        }
    </style>
</head>

修改ueditor.config.js中serverUrl的值爲加載後臺config.json配置項的接口路徑

// 服務器統一請求接口路徑
, serverUrl: window.CTX + "/ueditor/config"

8.訪問查看後端配置項

運行項目,訪問路徑http://localhost:8080/ue/ueditor/config?action=config,如下圖所示則表示可讀取到config.json文件。
訪問config.json
此時點擊多圖上傳,上傳出現未找到上傳數據
未找到上傳數據
debug發現BinaryUploader類無法獲取到字節流,原因是因爲SpringMVC框架對含字節流的request進行了處理,此處傳的是處理過的request,故獲取不到字節流。此時採用SpringMVC框架的解析器MultipartResolver。修改BinaryUploader源碼如下:

package com.solang.ueditor.upload;

import com.solang.ueditor.PathFormat;
import com.solang.ueditor.define.AppInfo;
import com.solang.ueditor.define.BaseState;
import com.solang.ueditor.define.FileType;
import com.solang.ueditor.define.State;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class BinaryUploader {

	public static final State save(HttpServletRequest request,
			Map<String, Object> conf) {
		if (!ServletFileUpload.isMultipartContent(request)) {
			return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
		}
		try {
			MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
			MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());
			if(multipartFile==null){
				return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
			}

			String savePath = (String) conf.get("savePath");
			String originFileName = multipartFile.getOriginalFilename();
			String suffix = FileType.getSuffixByFilename(originFileName);

			originFileName = originFileName.substring(0,
					originFileName.length() - suffix.length());
			savePath = savePath + suffix;

			long maxSize = ((Long) conf.get("maxSize")).longValue();

			if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
				return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
			}

			savePath = PathFormat.parse(savePath, originFileName);

			String physicalPath = (String) conf.get("rootPath") + savePath;
			
			InputStream is = multipartFile.getInputStream();
			State storageState = StorageManager.saveFileByInputStream(is,
					physicalPath, maxSize);
			is.close();

			if (storageState.isSuccess()) {
				storageState.putInfo("url", PathFormat.format(savePath));
				storageState.putInfo("type", suffix);
				storageState.putInfo("original", originFileName + suffix);
			}

			return storageState;
		} catch (IOException e) {
		}
		return new BaseState(false, AppInfo.IO_ERROR);
	}

	private static boolean validType(String type, String[] allowTypes) {
		List<String> list = Arrays.asList(allowTypes);

		return list.contains(type);
	}
	
}

此處physicalPath即爲上傳的物理路徑,是上傳到rootPath目錄下的。

9.修改config.json上傳路徑

由於UEditor上傳的路徑比較深,修改config.json的上傳路徑,將帶有PathFormat後綴的參數值去掉/ueditor/jsp/upload前綴
修改config.json上傳保存路徑
此時運行項目,上傳圖片發現圖片上傳成功,上傳路徑
圖片上傳路徑
但是編輯器圖片不顯示
上傳圖片不顯示
因爲把圖片存在E盤upload文件夾下了,而spring並沒有對E盤upload目錄進行映射。此時我們加入路徑映射。打開application.properties文件,添加如下代碼

spring.mvc.static-path-pattern=/**
spring.resources.static-locations=file:${web.upload-path},classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

此時運行項目,發現圖片還是不能正常顯示,如果沒有定義項目名那麼能正常顯示。由於項目定義了項目名,所以config.json需要定義項目名訪問前綴,即UrlPrefix結尾的參數對應的值。本博客定義爲/ue
定義文件路徑訪問前綴
此時想到如果項目名變化的話(畢竟SpringBoot改項目名很方便),這樣固定寫法很不好,所以將此配置到後臺代碼中。

修改ConfigManager源碼的initEnv方法,順便把SpringBoot打成jar包運行,在jar包裏無法以ClassLoader.getResource().getPath()獲得的路徑讀取文件的問題解決,需要使用Class類的getResourceAsStream()來讀取。

private void initEnv () throws FileNotFoundException, IOException {
		File file = new File( this.originalPath );
		if ( !file.isAbsolute() ) {
			file = new File( file.getAbsolutePath() );
		}
		
		this.parentPath = file.getParent();
		
		//String configContent = this.readFile( this.getConfigPath() );
		String configContent = this.filter(IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream("config.json"), "utf-8"));

		try{
			JSONObject jsonConfig = new JSONObject( configContent );
			/* 圖片訪問路徑前綴 */
			jsonConfig.put("imageUrlPrefix", contextPath);
			/* 圖片訪問路徑前綴 */
			jsonConfig.put("scrawlUrlPrefix", contextPath);
			/* 圖片訪問路徑前綴 */
			jsonConfig.put("snapscreenUrlPrefix", contextPath);
			/* 圖片訪問路徑前綴 */
			jsonConfig.put("catcherUrlPrefix", contextPath);
			/* 視頻訪問路徑前綴 */
			jsonConfig.put("videoUrlPrefix", contextPath);
			/* 文件訪問路徑前綴 */
			jsonConfig.put("fileUrlPrefix", contextPath);
			/* 圖片訪問路徑前綴 */
			jsonConfig.put("imageManagerUrlPrefix", contextPath);
			/* 文件訪問路徑前綴 */
			jsonConfig.put("fileManagerUrlPrefix", contextPath);
			this.jsonConfig = jsonConfig;
		} catch ( Exception e ) {
			this.jsonConfig = null;
		}
		
	}

此時代碼裏設置的路徑前綴會覆蓋config.json裏對應參數配置的值。

運行項目,上傳圖片發現圖片上傳成功並能在編輯器顯示。
上傳成功並顯示成功

10.在線管理

此時點擊在線管理(附件中的在線附件也是同樣的問題),發現圖片路徑顯示有問題
在線管理顯示問題
修改FileManager的getPath方法,將rootPath路徑E:/upload/替換爲/

private String getPath ( File file ) {
	// String path = file.getAbsolutePath();
	// return path.replace( this.rootPath, "/" );
	String path = PathFormat.format(file.getAbsolutePath());
	return path.replace(this.rootPath, "/" );	
}

此時在線管理也能正常顯示圖片了
在線管理顯示正常

至於UEditor的靜態資源存放路徑使用ueditors而不是ueditor,是因爲使用ueditor文件夾在谷歌瀏覽器上多圖上傳和附件上傳按鈕不能點擊,其它瀏覽器能正常點擊,不清楚具體原因,文件夾名改下就好了。

11.自定義上傳接口

參見UEditor官方文檔,可自定義上傳接口。
如何自定義請求地址
後端請求規範

本文參考:
SpringBoot整合UEditor教程
很詳細的SpringBoot整合UEditor教程
UEditor多圖上傳在線管理,附件在線附件顯示路徑問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章