最近用使用富文本编辑器,之前一直使用kindeditor和eWebEditor来着,有同事给推荐说使用百度推出的Ueditor,所以咯,自己新项目就将它引进来了,这里说一下心得,
说实话,Ueditor的官网文档真的一般,但是还是能让人看懂的,只不过有些地方写法实在操蛋。不过简单的上手还是很容易的,好了,废话不多说,直接上干货。
一、简单的使用
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 4 <!-- ueditor编辑器使用的js文件 --> 5 <script type="text/javascript" charset="utf-8" src="${ctx}/scripts/ueditor/ueditor.config.js"></script> 6 <script type="text/javascript" charset="utf-8" src="${ctx}/scripts/ueditor/ueditor.all.js"> </script> 7 <script type="text/javascript" charset="utf-8" src="${ctx}/scripts/ueditor/lang/zh-cn/zh-cn.js"></script> 8 9 <html> 10 <head> 11 <title>功能管理</title> 12 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 13 <script type="text/javascript"> 14 var ue; 15 // 初始化函数 16 $(document).ready(function() { 17 mini.parse(); 18 ue = UE.getEditor('container', { 19 serverUrl: "${ctx}/system/authority/getImgServer.ac", 20 toolbars: [ 21 [ 22 'bold', //加粗 23 'indent', //首行缩进 24 'snapscreen', //截图 25 'italic', //斜体 26 'underline', //下划线 27 'strikethrough', //删除线 28 'fontborder', //字符边框 29 'formatmatch', //格式刷 30 'source', //源代码 31 'horizontal', //分隔线 32 'removeformat', //清除格式 33 'insertcode', //代码语言 34 'fontfamily', //字体 35 'fontsize', //字号 36 'selectall', //全选 37 'print', //打印 38 'preview', //预览 39 'paragraph', //段落格式 40 'horizontal', //分隔线 41 'simpleupload', //单图上传 42 'insertimage', //多图上传 43 'removeformat', //清除格式 44 'date', //日期 45 'time', //时间 46 'link', //超链接 47 'unlink', //取消链接 48 'emotion', //表情 49 'spechars', //特殊字符 50 'searchreplace', //查询替换 51 'help', //帮助 52 'justifyleft', //居左对齐 53 'justifyright', //居右对齐 54 'justifycenter', //居中对齐 55 'justifyjustify', //两端对齐 56 'forecolor', //字体颜色 57 'backcolor', //背景色 58 'insertorderedlist', //有序列表 59 'insertunorderedlist', //无序列表 60 'fullscreen', //全屏 61 'imagecenter', //居中 62 'lineheight', //行间距 63 'edittip ', //编辑提示 64 'customstyle', //自定义标题 65 'touppercase', //字母大写 66 'tolowercase', //字母小写 67 'autotypeset', //自动排版 68 ] 69 ], 70 autoHeightEnabled: true, 71 autoFloatEnabled: true 72 }); 73 74 75 }); 76 77 78 79 80 81 82 </script> 83 </head> 84 <body> 85 86 <script id="container" name="describes" type="text/plain" style="100%;height:350px;"></script> 87 88 89 90 </body> 91 </html>
通过代码片段可以看到
<script id="container" name="describes" type="text/plain" style="100%;height:350px;"></script>
这句话中 name的名字为describes 那么表单提交的话,提交到后台,只需要获取这个describes参数就可以拿到前台传递到后台的富文本内容了,
如果项目是使用struts2的框架的话,则只需要再后台的action中写一个叫describes的属性,富文本内容就被自动注入到这个属性中了。
ok,拿到前台提交过来的值后,就不需要我在说了吧,各种增删改查还不是随自己的心意去写咯。
二、搭建图片服务器后台
在上述代码中可以看到,在初始化编辑器的时候有这么一句话
serverUrl: "${ctx}/system/authority/getImgServer.ac",
这句话是重写了它验证后台是否符合他的要求的路径。
默认他会调用jsp/controller.jsp这个路径
我这里贴一下我后台处理的代码
1 package cfs.system.authority.action; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.net.URLDecoder; 10 import java.util.UUID; 11 12 import net.sf.json.JSONArray; 13 import net.sf.json.JSONObject; 14 import cfs.coom.action.BaseEditAction; 15 import cfs.core.constant.CfsConstant; 16 import cfs.core.util.Util; 17 18 19 public class AuthorityAction extends BaseEditAction{ 20 private static final long serialVersionUID = 1L; 21 //图片服务器接收跳转使用的action 22 private String action; 23 //上传的图片 24 private File upfile; 25 //上传图片名称 26 private String upfileFileName; 27 //上传图片类型 28 private String upfileContentType; 29 30 31 32 33 /** 34 * 获取 上传的图片 35 * 36 * @return 上传的图片 37 */ 38 public File getUpfile() { 39 return upfile; 40 } 41 42 /** 43 * 设置 上传的图片 44 * 45 * @param upfile 上传的图片 46 */ 47 public void setUpfile(File upfile) { 48 this.upfile = upfile; 49 } 50 51 /** 52 * 获取 上传图片名称 53 * 54 * @return 上传图片名称 55 */ 56 public String getUpfileFileName() { 57 return upfileFileName; 58 } 59 60 /** 61 * 设置 上传图片名称 62 * 63 * @param upfileFileName 上传图片名称 64 */ 65 public void setUpfileFileName(String upfileFileName) { 66 this.upfileFileName = upfileFileName; 67 } 68 69 /** 70 * 获取 上传图片类型 71 * 72 * @return 上传图片类型 73 */ 74 public String getUpfileContentType() { 75 return upfileContentType; 76 } 77 78 /** 79 * 设置 上传图片类型 80 * 81 * @param upfileContentType 上传图片类型 82 */ 83 public void setUpfileContentType(String upfileContentType) { 84 this.upfileContentType = upfileContentType; 85 } 86 87 /** 88 * 获取 图片服务器接收跳转使用的action 89 * 90 * @return 图片服务器接收跳转使用的action 91 */ 92 public String getAction() { 93 return action; 94 } 95 96 /** 97 * 设置 图片服务器接收跳转使用的action 98 * 99 * @param action 图片服务器接收跳转使用的action 100 */ 101 public void setAction(String action) { 102 this.action = action; 103 } 104 105 106 107 108 109 /** 110 * 读取某个文件夹下的所有文件 111 */ 112 public String readfile(String filepath) throws Exception { 113 String name=""; 114 File file = new File(filepath); 115 if (!file.isDirectory()) { 116 System.out.println("文件"); 117 System.out.println("path=" + file.getPath()); 118 System.out.println("absolutepath=" + file.getAbsolutePath()); 119 System.out.println("name=" + file.getName()); 120 121 } else if (file.isDirectory()) { 122 String[] filelist = file.list(); 123 for (int i = 0; i < filelist.length; i++) { 124 File readfile = new File(filepath + "\" + filelist[i]); 125 if (!readfile.isDirectory()) { 126 name += readfile.getName()+"=|="; 127 128 }else if (readfile.isDirectory()) { 129 continue; 130 } 131 } 132 133 } 134 135 return name; 136 } 137 138 139 /** 140 * 验证图片服务器是否存在. 141 * 142 * @Title: getImgServer 143 * @author lmoran@163.com 144 * @return 145 * @throws Exception 146 */ 147 public String getImgServer() throws Exception{ 148 //如果是验证后台是否正常则走此段代码 149 if("config".equals(action)){ 150 JSONObject jobj = new JSONObject(); 151 jobj.put("imageActionName", "uploadimage"); 152 jobj.put("imageFieldName", "upfile"); 153 jobj.put("imageMaxSize", 2048000); 154 jobj.put("imageAllowFiles", JSONArray.fromObject(new String[]{".png",".jpg",".jpeg",".gif",".bmp"})); 155 jobj.put("imageCompressEnable", "true"); 156 jobj.put("imageCompressBorder", "1600"); 157 jobj.put("imageInsertAlign", "none"); 158 jobj.put("imageUrlPrefix", ""); 159 jobj.put("scrawlActionName", "uploadscrawl"); 160 jobj.put("scrawlFieldName", "upfile"); 161 jobj.put("scrawlMaxSize", 2048000); 162 jobj.put("scrawlUrlPrefix", ""); 163 jobj.put("scrawlInsertAlign", "none"); 164 jobj.put("snapscreenActionName", "uploadimage"); 165 jobj.put("snapscreenUrlPrefix", ""); 166 jobj.put("catcherLocalDomain", JSONArray.fromObject(new String[]{"127.0.0.1","localhost","img.baidu.com"})); 167 jobj.put("catcherActionName", "catchimage"); 168 jobj.put("catcherFieldName", "source"); 169 jobj.put("catcherUrlPrefix", ""); 170 jobj.put("catcherMaxSize", 2048000); 171 jobj.put("catcherAllowFiles", JSONArray.fromObject(new String[]{".png",".jpg",".jpeg",".gif",".bmp"})); 172 jobj.put("videoActionName", "uploadvideo"); 173 jobj.put("videoFieldName", "upfile"); 174 jobj.put("videoUrlPrefix", ""); 175 jobj.put("videoMaxSize", 102400000); 176 jobj.put("videoAllowFiles", JSONArray.fromObject(new String[]{".flv",".swf",".mkv",".avi",".rm",".rmvb",".mpeg",".mpg",".ogg",".ogv",".mov",".wmv",".mp4",".webm",".mp3",".wav",".mid"})); 177 jobj.put("fileActionName", "uploadfile"); 178 jobj.put("fileFieldName", "upfile"); 179 jobj.put("fileUrlPrefix", ""); 180 jobj.put("fileMaxSize", 51200000); 181 jobj.put("fileAllowFiles", JSONArray.fromObject(new String[]{".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"})); 182 jobj.put("imageManagerActionName", "listimage"); 183 jobj.put("imageManagerListPath", "/cfs/ueditor/upload/image/"); 184 jobj.put("imageManagerListSize", 20); 185 jobj.put("imageManagerUrlPrefix", ""); 186 jobj.put("imageManagerInsertAlign", "none"); 187 jobj.put("imageManagerAllowFiles", JSONArray.fromObject(new String[]{".png",".jpg",".jpeg",".gif",".bmp"})); 188 jobj.put("fileManagerActionName", "listfile"); 189 jobj.put("fileManagerListPath", "/cfs/ueditor/upload/file/"); 190 jobj.put("fileManagerUrlPrefix", ""); 191 jobj.put("fileManagerListSize", 20); 192 jobj.put("fileManagerAllowFiles", JSONArray.fromObject(new String[]{".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"})); 193 System.out.println(jobj.toString()); 194 writeToPage(jobj.toString()); 195 //如果是上传图片的action则跳转到上传图片方法中 196 }else if("uploadimage".equals(action)){ 197 return uploadimage(); 198 }else if("listimage".equals(action)){ 199 return listimage(); 200 } 201 202 203 return null; 204 } 205 206 207 208 /** 209 * 使用富文本上传图片. 210 * 211 * @Title: uploadimage 212 * @author lmoran@163.com 213 * @return 214 * @throws Exception 215 */ 216 public String uploadimage() throws Exception{ 217 String type=".png"; 218 if(upfileFileName.indexOf(".")!=-1){ 219 type=upfileFileName.substring(upfileFileName.lastIndexOf(".")); 220 } 221 222 String name=UUID.randomUUID().toString()+type; 223 String url=CfsConstant.UEDITOR_UPLOAD_IMAGE+ name; 224 String path = getSession().getServletContext() 225 .getRealPath("")+url; 226 File file = new File(path); 227 if (!file.exists()) { 228 file.createNewFile(); 229 } 230 FileOutputStream fos = new FileOutputStream(file); 231 InputStream imgin = new FileInputStream(upfile); 232 byte[] imgbyte = toByteArray(imgin); 233 imgin.close(); 234 fos.write(imgbyte); 235 fos.close(); 236 JSONObject jobj = new JSONObject(); 237 jobj.put("original", name); 238 jobj.put("name", name); 239 jobj.put("url", File.separator+ "cfs"+url); 240 jobj.put("size", upfile.length()); 241 jobj.put("type", type); 242 jobj.put("state", "SUCCESS"); 243 writeToPage(jobj.toString()); 244 return null; 245 } 246 247 248 /** 249 * 富文本组件,在线管理功能. 250 * 251 * @Title: listimage 252 * @author lmoran@163.com 253 * @return 254 * @throws Exception 255 */ 256 private String listimage() throws Exception { 257 String path = getSession().getServletContext() 258 .getRealPath("")+CfsConstant.UEDITOR_UPLOAD_IMAGE; 259 String str=readfile(path); 260 JSONArray ja=new JSONArray(); 261 int len=0; 262 if(!Util.isNullOrEmpty(str)&&!str.equals("=|=")){ 263 str=str.substring(0,str.lastIndexOf("=|=")); 264 String[] strs=str.split("=\|="); 265 len=str.length(); 266 String namePath=Util.getString("resource", "server_path")+"cfs"+CfsConstant.UEDITOR_UPLOAD_IMAGE; 267 for (String s : strs) { 268 JSONObject obj=new JSONObject(); 269 obj.put("url", namePath+s); 270 obj.put("mtime", 1467300922); 271 ja.add(obj); 272 } 273 } 274 JSONObject jobj = new JSONObject(); 275 jobj.put("state", "SUCCESS"); 276 jobj.put("list", ja); 277 jobj.put("start", 0); 278 jobj.put("total", len); 279 writeToPage(jobj.toString()); 280 return null; 281 } 282 283 284 /** 285 * 将InputStream转换成byte数组. 286 * 287 * @Title: toByteArray 288 * @author liufei12581@sinosoft.com.cn 289 * @param in 字节流 290 * @return byte数组格式的数据 291 * @throws IOException 292 */ 293 public byte[] toByteArray(InputStream in) throws IOException { 294 ByteArrayOutputStream out = new ByteArrayOutputStream(); 295 byte[] buffer = new byte[1024 * 4]; 296 int n = 0; 297 while ((n = in.read(buffer)) != -1) { 298 out.write(buffer, 0, n); 299 } 300 return out.toByteArray(); 301 } 302 303 304 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE struts PUBLIC 3 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 4 "http://struts.apache.org/dtds/struts-2.0.dtd"> 5 <struts> 6 <package name="authority" extends="cfs-default" namespace="/system/authority"> 7 8 <!-- 验证图片服务器--> 9 <action name="getImgServer" class="AuthorityAction" method="getImgServer"></action> 10 11 12 </package> 13 14 </struts>
注意:其中action为config表示是验证后台是否符合要求的代码,需要你返回一段json
我从官网示例中测出来的json格式:http://ueditor.baidu.com/server/ueditor/controller.php?action=config&&noCache=1467768503808
1 {"imageActionName":"uploadimage","imageFieldName":"upfile","imageMaxSize":2048000,"imageAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp"],"imageCompressEnable":true,"imageCompressBorder":1600,"imageInsertAlign":"none","imageUrlPrefix":"","imagePathFormat":"/server/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}","scrawlActionName":"uploadscrawl","scrawlFieldName":"upfile","scrawlPathFormat":"/server/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}","scrawlMaxSize":2048000,"scrawlUrlPrefix":"","scrawlInsertAlign":"none","snapscreenActionName":"uploadimage","snapscreenPathFormat":"/server/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}","snapscreenUrlPrefix":"","snapscreenInsertAlign":"none","catcherLocalDomain":["127.0.0.1","localhost","img.baidu.com"],"catcherActionName":"catchimage","catcherFieldName":"source","catcherPathFormat":"/server/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}","catcherUrlPrefix":"","catcherMaxSize":2048000,"catcherAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp"],"videoActionName":"uploadvideo","videoFieldName":"upfile","videoPathFormat":"/server/ueditor/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}","videoUrlPrefix":"","videoMaxSize":102400000,"videoAllowFiles":[".flv",".swf",".mkv",".avi",".rm",".rmvb",".mpeg",".mpg",".ogg",".ogv",".mov",".wmv",".mp4",".webm",".mp3",".wav",".mid"],"fileActionName":"uploadfile","fileFieldName":"upfile","filePathFormat":"/server/ueditor/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}","fileUrlPrefix":"","fileMaxSize":51200000,"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","imageManagerListPath":"/server/ueditor/upload/image/","imageManagerListSize":20,"imageManagerUrlPrefix":"","imageManagerInsertAlign":"none","imageManagerAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp"],"fileManagerActionName":"listfile","fileManagerListPath":"/server/ueditor/upload/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"]}
其中action为uploadimage时表示图片上传,这个可以改写,上面的验证时的返回的json其实就是对下面操作的设置,但是有一点比较恶心的是貌似就几个字段设置管用其他
例如图片路径啥的都不管用,这里图片上传也需要返回一个json
我从官网示例中测出来的json格式:http://ueditor.baidu.com/server/ueditor/controller.php?action=uploadimage
1 {"original":"demo.jpg","name":"demo.jpg","url":"/server/ueditor/upload/image/demo.jpg","size":"99697","type":".jpg","state":"SUCCESS"}
其中action为listimage表示图片管理,这个也可以改写,和上面图片上传一样
我从官网示例中测数来的json格式:http://ueditor.baidu.com/server/ueditor/controller.php?action=config&&noCache=1467768503808
1 {"imageActionName":"uploadimage","imageFieldName":"upfile","imageMaxSize":2048000,"imageAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp"],"imageCompressEnable":true,"imageCompressBorder":1600,"imageInsertAlign":"none","imageUrlPrefix":"","imagePathFormat":"/server/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}","scrawlActionName":"uploadscrawl","scrawlFieldName":"upfile","scrawlPathFormat":"/server/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}","scrawlMaxSize":2048000,"scrawlUrlPrefix":"","scrawlInsertAlign":"none","snapscreenActionName":"uploadimage","snapscreenPathFormat":"/server/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}","snapscreenUrlPrefix":"","snapscreenInsertAlign":"none","catcherLocalDomain":["127.0.0.1","localhost","img.baidu.com"],"catcherActionName":"catchimage","catcherFieldName":"source","catcherPathFormat":"/server/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}","catcherUrlPrefix":"","catcherMaxSize":2048000,"catcherAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp"],"videoActionName":"uploadvideo","videoFieldName":"upfile","videoPathFormat":"/server/ueditor/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}","videoUrlPrefix":"","videoMaxSize":102400000,"videoAllowFiles":[".flv",".swf",".mkv",".avi",".rm",".rmvb",".mpeg",".mpg",".ogg",".ogv",".mov",".wmv",".mp4",".webm",".mp3",".wav",".mid"],"fileActionName":"uploadfile","fileFieldName":"upfile","filePathFormat":"/server/ueditor/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}","fileUrlPrefix":"","fileMaxSize":51200000,"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","imageManagerListPath":"/server/ueditor/upload/image/","imageManagerListSize":20,"imageManagerUrlPrefix":"","imageManagerInsertAlign":"none","imageManagerAllowFiles":[".png",".jpg",".jpeg",".gif",".bmp"],"fileManagerActionName":"listfile","fileManagerListPath":"/server/ueditor/upload/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"]}
目前来讲项目中只需要实现图片的功能,例如音频视频也可以设置,返回的json格式大家可以自己去官网检测一下,总体来说功能还是不错的,比较容易上手,但是官网的api实在太一般。
最后还有一点要值得注意的是:它自己有初始化的方法,和jquery的初始化方法加载的时间顺序不太一样,最好用他自己的初始化,例如我想在一个页面一加载完就禁用掉不让用户编辑
那么直接使用它自己提供的初始化数据后的事件即可,
1 var ue; 2 // 初始化函数 3 $(document).ready(function() { 4 mini.parse(); 5 ue = UE.getEditor('container', { 6 serverUrl: "${ctx}/system/authority/getImgServer.ac", 7 toolbars: [ 8 ["fullscreen"] 9 ], 10 autoHeightEnabled: true, 11 autoFloatEnabled: true 12 }); 13 ue.addListener( 'ready', function( editor ) { 14 ue.setDisabled("fullscreen"); //编辑器加载完成后,禁用编辑器 15 16 } ); 17 18 });