该部分主要是ueditor的使用,去掉ueditor的jsp依赖,自定义图片上传路径,完全解除对百度ueditor.jar的使用,下载utf8-jsp版本的话就会看到jsp目录下会有个ueditor.jar,这个jar在maven仓库是没有的。喜欢看源码的筒子请下载ueditor源码,里面有jsp版本的jar包的源代码。
构建工程
下载utf8-jsp版本,目录结构如下所示:
我这里是用的是springboot的工程,其他的也一样,将下载的utf8-jsp复制到static目录下,我这里已经将其该名成了ueditor,改名随意,可以不改。
①jsp目录下的config.json复制到resource目录,ueditor每次实例化都会读取config.json,我们自己来提供这个读取接口。
②删除jsp目录,脱离jsp以及相关的jar包,读取配置文件接口自己写,上传用自己的接口。
③由于项目的html文件不可能一并写在ueditor目录下,所以我已将自带的index.html移动到了static目录下,这个就相当于自己写的html了,别忘了改index.html里面引入的js资源的路径。
确定配置文件获取路径
第一步:打开ueditor.config.js文件。
// window.UEDITOR_HOME_URL = ""; var URL = window.UEDITOR_HOME_URL || getUEBasePath(); /** * 配置项主体。注意,此处所有涉及到路径的配置别遗漏URL变量。 */ window.UEDITOR_CONFIG = { //为编辑器实例添加一个路径,这个不能被注释 UEDITOR_HOME_URL: URL // 服务器统一请求接口路径 , serverUrl: URL + "servlet"
Window.UEDITOR_HOME_URL可以不用管他。
来看服务器统一请求接口路径,这个路径就是获取配置文件,上传等接口的路径,由于上传路径等哈会通过其他方式配置成使用我们自己的上传路径,所以这里这个路径就只是获取配置文件用了。
我这里配置得是URL+”servlet”,具体咋配自己喜欢,但是"URL+"是必须的。
第二步:写好启动类,启动工程,访问index.html页面,打开F12调试,刷新页面,你将看到下图的内容,提示“请求后台配置项http错误,上传功能将不能正常使用”。
重要:这个路径就是ueditor获取配置文件的路径,所以这里我们写配置文件的获取的接口就按这个来写就行了,由于只是获取配置文件的接口,所以后边的参数action就不重要了,这个action主要是用来是获取配置文件还是上传用的。这里由于我们上传用的自己的,已经没用百度自己的jar了,所以这个就没用了。
第三步:写获取配置文件的Controller,写入到流中(参照ueditor自己的controller.jsp)。
@RestController @RequestMapping("/ueditor") public class UeditorController { @RequestMapping("/servlet") public void servlet(HttpServletRequest request, HttpServletResponse response) { try { PrintWriter out = response.getWriter(); request.setCharacterEncoding("utf-8"); response.setHeader("Content-Type", "text/html"); String action = request.getParameter("action"); String result = ""; if (action.equals("config")) { MyConfigManager configManager= MyConfigManager.getInstance(); result=configManager.getAllConfig().toString(); } out.write(result); } catch (IOException e) { e.printStackTrace(); } } }
MyConfigManager.java
public final class MyConfigManager { private final Logger logger = LoggerFactory.getLogger(MyConfigManager.class); private JSONObject jsonConfig = null; private static MyConfigManager manager; private MyConfigManager() throws IOException { this.initEnv(); } public static MyConfigManager getInstance() { if (manager != null) { //ueditor每次实例化都会获取配置文件,单列模式,防止一直new对象 return manager; } try { manager = new MyConfigManager(); return manager; } catch (Exception var4) { return null; } } public boolean valid() { return this.jsonConfig != null; } public JSONObject getAllConfig() { if (this.jsonConfig != null) return this.jsonConfig; else { JSONObject state=new JSONObject(); //将“配置文件初始化失败”转成unicode编码返回 state.put("state","\\u914d\\u7f6e\\u6587\\u4ef6\\u521d\\u59cb\\u5316\\u5931\\u8d25"); return state; } } private void initEnv() throws IOException { String configContent = this.readFile(); try { JSONObject e = JSONObject.parseObject(configContent); this.jsonConfig = e; } catch (Exception var4) { this.jsonConfig = null; } } private String readFile() throws IOException { StringBuilder builder = new StringBuilder(); logger.info("开始读取文件:"); Resource resource = new ClassPathResource("config.json"); try { InputStreamReader reader = new InputStreamReader(resource.getInputStream(), "UTF-8"); BufferedReader bfReader = new BufferedReader(reader); String tmpContent = null; while ((tmpContent = bfReader.readLine()) != null) { builder.append(tmpContent); } logger.info("文件读取完成:"); bfReader.close(); } catch (UnsupportedEncodingException var6) { logger.info("文件读取出错:"); ; } return this.filter(builder.toString()); } private String filter(String input) { return input.replaceAll("/\\*[\\s\\S]*?\\*/", ""); } }
这个时候再启动项目,访问index.html页面,就不会报错了,但是上传是不能成功的,因为我们这个接口是专门获取配置文件的,对上传没有任何作用。
之前说了,ueditor.config.js中配置的统一路径就是这个接口,那个action得值就是用来区别到底是上传,还是获取配置文件。
上传配置
第一步:写文件上传接口,
ueditor的图片上传,返回ueditor能识别的参数类型,这个表单名字files是在config.json里面配置过的,默认为upfile,这里演示的仅仅是是否上传成功,所以上传的图片全部默认保存到了指定的路径,ueditor上是不能显示的。
config.json
/* 上传图片配置项 */ "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ "imageFieldName": "files", /* 提交的图片表单名称 */ "imageMaxSize": 2048000, /* 上传大小限制,单位B */
UploadController.java
@RestController public class UploadController { @RequestMapping("/upload") public Object upload(@RequestParam(value = "files") MultipartFile files, HttpServletRequest req) { String rootPath = req.getServletContext().getRealPath("/"); System.out.println(rootPath); UeditorResponse ur = new UeditorResponse(); ur.setType(files.getOriginalFilename()); ur.setOriginal(files.getOriginalFilename()); try { System.out.println(files.getName()); System.out.println(files.getOriginalFilename()); String path = "D:/" + files.getOriginalFilename(); files.transferTo(new File(path)); ur.setUrl(path); ur.setState("SUCCESS"); } catch (IOException e) { e.printStackTrace(); ur.setState("图片上传失败"); return ur; } return ur; } @RequestMapping("/uploadbase64") public Object uploadbase64(String files) { System.out.println(files); UeditorResponse ur = new UeditorResponse(); savebase64(files, "D:/xxx.png"); ur.setState("SUCCESS"); ur.setUrl("url"); ur.setOriginal("xxx.png"); return ur; } //保存base64为图片 public Object savebase64(String file, String path) { file = file.substring(file.indexOf(",") + 1); System.out.println(file); try { BASE64Decoder decoder = new BASE64Decoder(); byte[] bytes = decoder.decodeBuffer(file); for (int i = 0; i < bytes.length; ++i) { if (bytes[i] < 0) {// 调整异常数据 bytes[i] += 256; } } InputStream in = new ByteArrayInputStream(bytes); FileOutputStream fos = new FileOutputStream(new File(path)); byte[] b = new byte[4096]; Integer len = -1; while ((len = in.read(b)) != -1) { fos.write(b, 0, len); } fos.flush(); in.close(); fos.close(); } catch (Exception e) { e.printStackTrace(); } return null; } }
Ueditor能够识别的返回值实体,UeditorResponse.java
public class UeditorResponse { //图片上传成功后返回获取图片的路径, //可以是一个二进制流的接口,也可以是图片地址得接口,总之这个路径必须是写在img标签内能够显示的 private String url; //上传状态信息,如果为"SUCCESS"(必须是大写),则表示上传成功,不为SUCCESS时页面提示信息就是state得值 private String state; private String type; private String original;
url:图片上传成功后返回获取图片的路径,可以是一个二进制流的接口,也可以是图片地址得接口,总之这个路径必须是写在img标签内能够显示的。
state:上传状态信息,如果为"SUCCESS"(必须是大写),则表示上传成功,不为SUCCESS时页面提示信息就是state得值
第二步:添加实例化ueditor指定上传路径的代码
打开index.html,找到ueditor实例化的部分。
在var ue=UE.getEditor(‘editor’);之后添加下面一段代码,覆盖UEditor中获取路径的方法,用来指定上传路径(也就是我们自己写的上传路径)。
uploadimage,截图和图片上传(config.json里面有注释)
uploadfile,附件上传
涂鸦用的是base64的编码,这种multipartfile的方式就不顶用了,可以重新再写一个base64的,用来上传涂鸦,如上述uploadbase64接口。
//实例化编辑器 var ue = UE.getEditor('editor'); UUE.Editor.prototype._bkGetActionUrl=UE.Editor.prototype.getActionUrl; UE.Editor.prototype.getActionUrl=function(action){ if (action == 'uploadimage'||action == 'uploadfile'){ return 'upload'; /* 这里填上你自己的上传图片的url */ }else if(action == 'uploadscrawl'){ return 'uploadbase64'; }else{ return this._bkGetActionUrl.call(this, action); } };
所有工作做完,再次访问index.html,测试一次图片上传,你可以发现,原来真的可以用了。
但是:再次提醒一次,这里演示的仅仅是是否上传成功,所以上传的图片全部默认保存到了指定的路径,ueditor上是不能显示的(自己看上传接口的代码)。
Demo地址:https://github.com/wtkid/workspace_G/tree/master/ideaprojects/spirngboot-ueditor
百度jar源码:https://github.com/wtkid/workspace_G/tree/master/ideaprojects/ueditorjar
图片上传图片太大出现滚动条
这个是ueditor自己本身就存在的,跟我们自己这种是否依赖jsp无关。
我们现在要设置图片上传后显示的时候最大宽度不超过屏幕。
第一步:取消style过滤,添加style到过滤白名单。
打开ueditor.config.js,找到图示位置,也就是img开头的那行,添加一个’style’.
header: [], hr: [], i: ['class', 'style'], img: ['src', 'alt', 'style', 'title', 'width', 'height', 'id', '_src', 'loadingclass', 'class', 'data-latex'], ins: ['datetime'], li: ['class', 'style'],
第二步:单张图片上传添加style代码
打开ueditor.all.js,找到图示大概24531行的位置,添加以下代码
loader.setAttribute('style', 'max-width:100%');
function callback(){ try{ var link, json, loader, body = (iframe.contentDocument || iframe.contentWindow.document).body, result = body.innerText || body.textContent || ''; json = (new Function("return " + result))(); link = me.options.imageUrlPrefix + json.url; if(json.state == 'SUCCESS' && json.url) { loader = me.document.getElementById(loadingId); loader.setAttribute('src', link); loader.setAttribute('_src', link); loader.setAttribute('style', 'max-width:100%'); loader.setAttribute('title', json.title || ''); loader.setAttribute('alt', json.original || ''); loader.removeAttribute('id'); domUtils.removeClasses(loader, 'loadingclass');
第三步:剪切板的图片粘贴或直接拖动图片进来时添加style
打开如图所示23771行部分,添加同样代码
if (filetype == 'image') { loadingHtml = '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme + '/images/spacer.gif" title="' + (me.getLang('autoupload.loading') || '') + '" >'; successHandler = function(data) { var link = urlPrefix + data.url, loader = me.document.getElementById(loadingId); if (loader) { loader.setAttribute('src', link); loader.setAttribute('_src', link); loader.setAttribute('style', 'max-width:100%'); loader.setAttribute('title', data.title || ''); loader.setAttribute('alt', data.original || ''); loader.removeAttribute('id'); domUtils.removeClasses(loader, 'loadingclass'); } };
第四步:多个图片同时上传时添加style
这个要改两个地方。
打开大概11170行的地方。
str = '<img src="' + ci.src + '" ' + (ci._src ? ' _src="' + ci._src + '" ' : '') + (ci.width ? 'width="' + ci.width + '" ' : '') + (ci.height ? ' height="' + ci.height + '" ' : '') + ' style="max-width:100%";'+ (ci['floatStyle'] == 'left' || ci['floatStyle'] == 'right' ? ' float:' + ci['floatStyle'] + ';"' : '') +'"'+ (ci.title && ci.title != "" ? ' title="' + ci.title + '"' : '') +
再打开大概11188行的位置,也就是上面那个if的else里面的代码。
for (var i = 0; ci = opt[i++];) { unhtmlData(ci); str = '<p ' + (ci['floatStyle'] == 'center' ? 'style="text-align: center" ' : '') + '><img src="' + ci.src + '" ' + (ci.width ? 'width="' + ci.width + '" ' : '') + (ci._src ? ' _src="' + ci._src + '" ' : '') + (ci.height ? ' height="' + ci.height + '" ' : '') + ' style="max-width:100%' + (ci['floatStyle'] && ci['floatStyle'] != 'center' ? 'float:' + ci['floatStyle'] + ';' : '') + (ci.border || '') + '" ' + (ci.title ? ' title="' + ci.title + '"' : '') + ' /></p>'; html.push(str); }
好了,这样就完美了,这个图片太大的问题,有需求的时候就用的住了。
Over~~