UEditor富文本编辑器整合经验分享(整合至SpringMVC)

转载于: https://blog.csdn.net/lixinyao5281/article/details/78878774

一、引言

前段时间开发邮件模块需要使用到一款富文本编辑器,综合考察之后选择了 UEditor——百度的富文本编辑器。在整合到项目的过程中,遇到了不少问题,困扰了不少时间,在整合过程中也参考了不少前辈们的文章收获良多,本文主要是谈谈自己在整合过程中遇到各种问题(或者网上甚少提到的)及UEditor自己的一些内部瑕疵,做为经验分享给大家,希望大家在以后的整合过程中避免可能会重复陷入的坑提供一些帮助和提醒。

在这里插入图片描述
图 UEditor工具条
在这里插入图片描述
图 UEditor功能展示

UEditor是一款功能相对比较强大的前端富文本编辑器,支持四种后台语言环境,比如 php,asp,asp.net,jsp 。 UEditor 是由百度「FEX前端研发团队」开发的所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码。

百度官方UEditor文档及下载地址为

http://fex.baidu.com/ueditor/

在这里插入图片描述
在这里插入图片描述

百度UEditor官网上,可以查看并下载UEditor源码,初始了解UEditor功能及体验。由于ueditor开发组是一个前端团队,而对后端实力较欠缺(官方原话),笔者在整合过程中发现其对后台的处理还有些瑕疵(比如图片上传及回显处理或文件上传及下载处理),特别是没有具体前后台交互的实际案例(能让开发者在本地实际运行的DEMO)开发者实际调试成功,便能快速地掌握前后台交互的机制。下图为百度FEX团队的对后端部署的说明

二、官方DEMO

官方下载地址

http://ueditor.baidu.com/website/download.html

在这里插入图片描述
本文以 JSP版本为例 下载UTF-8版本并解压

在这里插入图片描述

用浏览器打开index.html

在这里插入图片描述
看到demo界面,兴奋了一阵子,然而涉及到后台交互的功能(如图片文件上传),暂时是不能用的,按F12查看浏览器控制台发现有错误
在这里插入图片描述

由于官方demo没有后台代码的实际支撑,所以实际整合过程中会遇到各种问题,或许一时没有头绪,如果有一个实际能运行的案例就好了。

笔者参考csdn网站博主liuyazhang的一篇文章

http://blog.csdn.net/l1028386804/article/details/52389722

拜读之后才开始自己的整合之路,编写并提供了可实际运行的DEMO也是在博主的例子的基础之上,修复了若干问题后才整合成功的。解决了主要问题是,图片上传、存储、前端页面显示;文件上传、存储、前端页面下载.

三、 动手整合UEditor

3.1 ueditor整体植入结构

本例子整合工具使用的eclipse,用流行的idea当然也是可以的,ueditor插件目录如下所示
在这里插入图片描述

工程中需要添加以下jar包(Ueditor中就有),如果工程使用Mavan则添加到Mavan中
在这里插入图片描述
3.2 富文本页面入口index.jsp

引入富文本编辑入口页面index.jsp如下所示
在这里插入图片描述

 <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%
    	String path = request.getContextPath(); 
    	// 获得本项目的地址(例如: http://localhost:8080/MyApp/)赋值给basePath变量
    	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
    %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Ueditor</title>
    <script type="text/javascript">
    	var basePath = "<%=basePath%>";
    </script>
    <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="ueditor/ueditor.all.js"></script>
    <script type="text/javascript" src="ueditor/ueditor.config.js"></script>
    <script type="text/javascript" src="ueditor/lang/zh-cn/zh-cn.js"></script>
    <script type="text/javascript" src="ueditor/index.js"></script>
    </head>
    <body>
    	<div>
    		<textarea id="myEditor" style="width:100%;height:285px;"></textarea>
    	</div>
    </body>
    </html>

引用了ueditor.config.js,ueditor.all.js,zh-cn.js,index.js和jquery-1.12.0.min.js

控件容器载体可以用 ,

控件初始化方法 UE.getEditor(‘myEditor’)
在这里插入图片描述

$(function(){
	//富文本编辑器
	UE.getEditor('myEditor')
	
	UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl;
	UE.Editor.prototype.getActionUrl = function(action){
		if(action == '/upload/images'){
			return basePath+'/upload/images';
		}else{
			return this._bkGetActionUrl.call(this,action);
		}
	}
});

也可以使用

在这里插入图片描述在这里插入图片描述
无论是

3.2 关于config.json
在这里插入图片描述

/* 上传图片配置项 */
    "imageActionName": "/upload/images", /* 执行上传图片的action名称 */
    "imageFieldName": "upfile", /* 提交的图片表单名称 */
    "imageMaxSize": 2048000, /* 上传大小限制,单位B */
    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
    "imageCompressEnable": true, /* 是否压缩图片,默认是true */
    "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
    "imageUrlPrefix": "http://127.0.0.1:8080/shiroDemo", /* 图片访问路径前缀 */
    "imagePathFormat": "/ueditor/jsp/upload/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 */

很多资料都提到了config.json文件是配置参数的文件,然而笔者发现参数定义在本文件中并不起作用,实际上配置参数定义在ueditor.config.js文件中才会真正起到作用

3.3 关于ueditor.config.js

可以说是ueditor最重要的配置文件,后台配置基本定义在此。
在这里插入图片描述

官方文件如上所示,定义了serverUrl 服务器统一请求接口路径jsp/controller.jsp

在ueditor目录中能找到这个controller.jsp,这个jsp仅仅是用来模拟后台的入口,真实整合过程中应该是调用后台Controller类而不是这个jsp
整合完成之后的ueditor.config.js参考如下
在这里插入图片描述

 var URL = window.UEDITOR_HOME_URL || getUEBasePath();

    /**
     * 配置项主体。注意,此处所有涉及到路径的配置别遗漏URL变量。
     */
    window.UEDITOR_CONFIG = {

        //为编辑器实例添加一个路径,这个不能被注释
        UEDITOR_HOME_URL: URL
        //与工程名保持一致
        ,contextRootPath:'/shiroDemo'
        // 服务器统一请求接口路径
        , serverUrl: '../uedit/config'
        //图片上传后台类及方法
        ,imageActionName:'/upload/images'
        //允许上传图片格式
        ,imageAllowFiles: [".png", ".jpg", ".jpeg", ".gif", ".bmp"]	
    	,imageUrl:'/upload/viewImagesToPage?imagePath='
    	//文件上传后台类及方法
        ,fileActionName:'/upload/images'
        //允许上传文件格式
        ,fileAllowFiles: [".png", ".jpg", ".jpeg", ".gif", ".bmp",".flv",
                          ".swf",".mkv",".avi",".rm",".rmb",".mpeg",".mpg"
                          ,".ogg", ".wav",".cab",".pptx",".ogv",".mid"
                          ,".iso",".pdf",".mov",".rar",".doc",".txt",".wmv"
                          ,".zip",".docx",".md",".mp4",".webm",".tar",".gZ"
                          ,".7z",".xls",".xlsx",".ppt",".xml",".bz2"]	
    	//文件下载后台
       	,fileUrlPrefix:'/upload/fileDownLoad?'

contextRootPath :

由于整合过程中很多地方会用到工程根目录,这里就定义好即可,与工程名保持一致即可。

serverUrl:

服务器统一请求接口路径 比如 …/ueditor/config(参考UEditorController)

imageActionName:

定义了图片上传后台类及方法 比如 /resource/upload/images (参考UploadImageController)

imageUrl:

图片页面回显后台类及方法 比如 : /resource/upload/viewImagesToPage.do?imagePath=(参考UploadImageController)

fileActionName:

文件上传设置 比如 /resource/upload/images(参考UploadImageController)

fileUrlPrefix:

文件下载后台 比如 /ueditor/resource/upload/fileDownLoad.do?(参考UploadImageController)

3.4 serverUrl与服务器统一请求控制类UEditorController

本类替换原来官方提供的后台入口controller.jsp ,参考代码如下

  package com.controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.baidu.ueditor.ActionEnter;

@Controller
@Scope("prototype")
@RequestMapping("/uedit")
public class UEditorController {
	
	private static final Logger logger = Logger.getLogger(UEditorController.class);
	 
    @RequestMapping(value="/config")
    public void config(HttpServletRequest request, HttpServletResponse response) {
 
        response.setContentType("application/json");
        String rootPath = request.getSession()
                .getServletContext().getRealPath("/");
        System.out.println("进入UEditorController");
 
        try {
            String exec = new ActionEnter(request, rootPath).exec();
            PrintWriter writer = response.getWriter();
            writer.write(exec);
            writer.flush();
            writer.close();
            logger.info("上传图片");
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
}

本类是实现图片上传至服务指定目录并在页面回显的指定服务类,同时也是文件上传及下载的服务类,与配置文件ueditor.config.js中定义的以下参数有关联

imageActionName:

定义了图片上传后台类及方法 比如 /resource/upload/images

imageUrl:

图片页面回显后台类及方法 比如 : /resource/upload/viewImagesToPage.do?imagePath=

fileActionName:

文件上传设置 比如 /resource/upload/images

fileUrlPrefix:

文件下载后台 比如 /ueditor/resource/upload/fileDownLoad.do?

代码参考如下
图片文件上传及存储方法images

   package com.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.math.RandomUtils;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping(value="/upload")
public class UploadImageController {
	
	/**
	 * 上传图片
	 * @param file
	 * @param request
	 * @param response
	 * @return MultipartFile uploadFile,
	 */
	@ResponseBody
	@RequestMapping(value="/images",method = RequestMethod.POST)
	public Map<String, Object> images (@RequestParam(value = "file", required = false) MultipartFile file, HttpServletRequest request, HttpServletResponse response){
		Map<String, Object> params = new HashMap<String, Object>();
		if (file == null){
            System.out.println("未获得上传文件!");			
			return null;
		}
		try{
			 String filetype = request.getParameter("filetype")+"";
			 System.out.println("filetype:"+filetype);
			 String basePath = "";
			 if("image".equals(filetype)){
				 basePath = "d:/resources/static/images";
			 }else if("file".equals(filetype)){
				 basePath = "d:/resources/static/files";
			 }
			 if(basePath == null || "".equals(basePath)){
				 basePath = "d:/resources/static";  //与properties文件中lyz.uploading.url相同,未读取到文件数据时为basePath赋默认值
			 }
			 System.out.println("filename:"+file.getOriginalFilename());
			 String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1).toLowerCase();
			 String fileName = String.valueOf(System.currentTimeMillis()).concat("_").concat(String.valueOf(Math.random() * 1000)+1000).concat(".").concat(ext);
			 StringBuilder sb = new StringBuilder();
			 //拼接保存路径
			 sb.append(basePath).append("/").append(fileName);
			 
			 String visitUrl = basePath.concat("/"+fileName);
			 File f = new File(sb.toString());
			 if(!f.exists()){
				 f.getParentFile().mkdirs();
			 }
			 OutputStream out = new FileOutputStream(f);
			 FileCopyUtils.copy(file.getInputStream(), out);
			 params.put("state", "SUCCESS");
			 params.put("url", visitUrl);
			 params.put("size", file.getSize());
			 params.put("original", fileName);
			 params.put("type", file.getContentType());
			 params.put("filename", file.getOriginalFilename());
			 System.out.println("url:"+visitUrl+" original:"+fileName+" filename:"+file.getOriginalFilename()+" type:"+file.getContentType());
		} catch (Exception e){
			 params.put("state", "ERROR");
			 e.printStackTrace();
		}
		 return params;
	}

图片在JSP页面回显方法viewImagesToPage方法

   /**
	 * 供读取服务器上传成功的图片显示到jsp上使用(多个图片循环调用)
	 * @param request
	 * @param response
	 * @param imagePath  图片地址
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/viewImagesToPage")
	public String viewImagesToPage(HttpServletRequest request,HttpServletResponse response,
				@RequestParam(value = "imagePath", required = false) String imagePath) {
		System.out.println("imagePath:"+imagePath);
		ServletOutputStream out = null;
		FileInputStream ips = null;
		try {
			ips = new FileInputStream(new File(imagePath));
			response.setContentType("multipart/form-data");
			out = response.getOutputStream();
			// 读取文件流
			int i = 0;
			byte[] buffer = new byte[4096];
			while ((i = ips.read(buffer)) != -1) {
				// 写文件流
				out.write(buffer, 0, i);
			}
			out.flush();
			ips.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (ips != null) {
				try {
					ips.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}

文件在页面下载方法fileDownLoad

/**
	 * 下载文件
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/fileDownLoad",method = RequestMethod.GET)
	public void fileDownLoad(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 下载本地文件
		String url = request.getParameter("url")+"";
		String fileName = request.getParameter("filename")+"";
		//如果是IE浏览器,则用URLEncode解析
		String agent=request.getHeader("User-Agent").toLowerCase();
		if(agent.indexOf("mise")>0){
			fileName = URLEncoder.encode(fileName, "UTF-8");
		}else{//如果是谷歌、火狐则解析为ISO-8859-1
			fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
		}
		System.out.println("filename:"+fileName+" url:"+url);
		// 读到流中
		InputStream inStream = new FileInputStream(url);// 文件的存放路径
//		fileName = url.substring(url.lastIndexOf("/")+1);
//		System.out.println("filename:"+fileName);
		// 设置输出的格式
		response.reset();
//		response.setContentType("bin");
		response.setContentType("application/vnd.ms-excel;charset=utf-8");
		response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
		// 循环取出流中的数据
		byte[] b = new byte[100];
		int len;
		try {
			while ((len = inStream.read(b)) > 0)
				response.getOutputStream().write(b, 0, len);
			inStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

3.6 关于图片上传涉及 ueditor.all.js中的一些问题

图片上传至后台 MultipartFile为空

原码24486行涉及到图片上传的部分代码

name="’ +me.options.imageFieldName + '" ’ 需要与后台images方法中的 MultipartFilefile名称保持一致
在这里插入图片描述

如不然,则会取不到值MultipartFile对象为空

后端配置项没有正常加载,上传插件不能正常使用!

常出现于24557行me.getOpt(‘imageActionName’) 获值出错 原因为ueditor.config.js中未定义imageActionName 图片后台服务路径
在这里插入图片描述

注意:上面代码对图片上传的路径做了调整并添加文件类型为image的参数(为存储路径的参数)

上传后图片无法回显

原码24524行 对图片路径处理的调整 其中json.url 是后台方法image赋值过去的
在这里插入图片描述
浏览器控制台打印效果 (图片显示链接)
在这里插入图片描述
上传excel文件后,页面反显为txt图片
在这里插入图片描述

上传的明明是excle文件 显示的居然是txt图标 原因是原码中少了 对 xlsx文件的映射关系,这里属于ueditor的小瑕疵
在这里插入图片描述
解决办法是在原码中加入对xlsx类型文件的映射关系即可
在这里插入图片描述
再重试 .xlsx类文件上传,发现图标恢复正常。

3.7 关于附件上传的问题

attachment.html
在这里插入图片描述

建议不引用webuploader.min.js改为引用原webuploader.js以方便处理附件上传遇到的各种问题

文件上传路径

webuploader.js第6199行
在这里插入图片描述

添加以上三行代码取得文件路径为

文件类型参数为 file

附件上传路径问题

attachment.js第146行
在这里插入图片描述

actionUrl = editor.getOpt(‘fileActionName’),考虑不用getActionUrl方法

附件下载链接问题

attachment.js第560行
在这里插入图片描述

3.8 关于图片附件上传服务器存储路径的问题

对图片附件的存储路径定义在applications.properties文件中
在这里插入图片描述

后台的UploadImageController将对请求参数的不同将图片和附件存放在不同的目录中
在这里插入图片描述
在这里插入图片描述
3.9关于其它弹出控件被UEditor遮挡住的问题

在编辑页面如果使用其它弹出层控件比如树型选择控件时,发现树型控件弹出后还是被UEditor控件给遮挡住了。如下图所示。
在这里插入图片描述

这是由于树型弹出层 zIndex为 101 而UEditor的z-Index为999 故而被UEditor遮挡住

解决办法为 可以将UEditor的z-Index调低一些,将ueditor.all.js行8059 zIndex调成100即可
在这里插入图片描述

调整后,再看
在这里插入图片描述
弹出树形控件层在UEditor层之上,问题解决。

四、 案例分享

本文提供的完全与文章内容一致的案例,可供读者实际在本地运行

4.1 案例下载地址

http://download.csdn.net/download/lixinyao5281/10170693

4.2 运行准备工作

本案例由于是SpirngMVC整合需要连接Mysql数据库,数据库的连接配置文件为applicationContext.xml,配置举例如下
在这里插入图片描述

读者在本地配置好mysql数据库即可

图片上传按钮和附件上传按钮如下图左侧和右侧
在这里插入图片描述

实际运行效果如下 本地服务链接地址参考如下

http://127.0.0.1:8080/ueditor/index/page
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值