关于百度Editor富文本编辑器 自定义上传位置

时间:2021-05-27 06:11:47

 

因为要在网站上编辑富文本数据,所以直接采用百度的富文本编辑器,但是这个编辑器有个缺点,默认情况下,文件只能上传到网站的根目录,不能自定义路径。

而且json配置文件只能和controller.jsp在同一个目录下,不好管理。所以小淘气儿修改了部分源码以及配置了一个拦截器,实现了以上功能。

首先,将下载,并解压的文件夹复制到webapp目录下,如图:

                               关于百度Editor富文本编辑器 自定义上传位置

并将ueditor/jsp/下的config.json移动到resources目录下,

config.json是配置图片,文件,视频信息的json格式的文件。以下我就用图片讲解:

/* 前后端通信相关的配置,注释只允许使用多行方式 */
{


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

    /* 涂鸦图片上传配置项 */
    "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
    "scrawlFieldName": "upfile", /* 提交的图片表单名称 */
    "scrawlPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
    "scrawlUrlPrefix": "", /* 图片访问路径前缀 */
    "scrawlInsertAlign": "none",

    /* 截图工具上传 */
    "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
    "snapscreenPathFormat": "/ueditor/jsp/upload/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": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    "catcherUrlPrefix": "", /* 图片访问路径前缀 */
    "catcherMaxSize": 2048000, /* 上传大小限制,单位B */
    "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */

    /* 上传视频配置 */
    "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
    "videoFieldName": "upfile", /* 提交的视频表单名称 */
    "videoPathFormat": "/ueditor/jsp/upload/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": "/ueditor/jsp/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    "fileUrlPrefix": "", /* 文件访问路径前缀 */
    "fileMaxSize": 51200000, /* 上传大小限制,单位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": "/ueditor/jsp/upload/image/", /* 指定要列出图片的目录 */
    "imageManagerListSize": 20, /* 每次列出文件数量 */
    "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */
    "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
    "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */

    /* 列出指定目录下的文件 */
    "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
    "fileManagerListPath": "/ueditor/jsp/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"
    ] /* 列出的文件类型 */

}

 

imageUrlPrefix+imagePathFormat是图片的访问路径,也是图片显示的关键。

uploadRoot是我新增加的键,对应的value是图片上传绝对路径。

正常情况下,在加载ueditor编辑器时,会访问ueditor/jsp/controller.jsp:

controller.jsp代码:

    request.setCharacterEncoding( "utf-8" );
    response.setHeader("Content-Type" , "text/html");
    String rootPath = application.getRealPath( "/" );
    System.out.println(rootPath);
    out.write( new ActionEnter( request, rootPath ).exec() );

  在这里解析的config.json,

  在创建ActionEnter实例的时候,初始化ConfigManager类,其中ConfigManager类是关键。

 百度源代码:

  1 //
  2 // Source code recreated from a .class file by IntelliJ IDEA
  3 // (powered by Fernflower decompiler)
  4 //
  5 
  6 package com.baidu.ueditor;
  7 
  8 import java.io.BufferedReader;
  9 import java.io.File;
 10 import java.io.FileInputStream;
 11 import java.io.FileNotFoundException;
 12 import java.io.IOException;
 13 import java.io.InputStreamReader;
 14 import java.io.UnsupportedEncodingException;
 15 import java.util.HashMap;
 16 import java.util.Map;
 17 import org.json.JSONArray;
 18 import org.json.JSONObject;
 19 
 20 public final class ConfigManager {
 21     private final String rootPath;//绝对根路径
 22     private final String originalPath;
 23     private final String contextPath;
 24     private static final String configFileName = "config.json";
 25     private String parentPath = null;//controller.jsp的上级目录路径
 26     private JSONObject jsonConfig = null;//解析config.json后的json对象
 27     private static final String SCRAWL_FILE_NAME = "scrawl";
 28     private static final String REMOTE_FILE_NAME = "remote";
 29 
 30     private ConfigManager(String rootPath, String contextPath, String uri) throws FileNotFoundException, IOException {
 31         rootPath = rootPath.replace("\\", "/");
 32         this.rootPath = rootPath;
 33         this.contextPath = contextPath;
 34         if(contextPath.length() > 0) {
 35             this.originalPath = this.rootPath + uri.substring(contextPath.length());
 36         } else {
 37             this.originalPath = this.rootPath + uri;
 38         }
 39 
 40         this.initEnv();
 41     }
 42 
 43     public static ConfigManager getInstance(String rootPath, String contextPath, String uri) {
 44         try {
 45             return new ConfigManager(rootPath, contextPath, uri);
 46         } catch (Exception var4) {
 47             return null;
 48         }
 49     }
 50 
 51     public boolean valid() {
 52         return this.jsonConfig != null;
 53     }
 54 
 55     public JSONObject getAllConfig() {
 56         return this.jsonConfig;
 57     }
 58 
 59     public Map<String, Object> getConfig(int type) {
 60         HashMap conf = new HashMap();
 61         String savePath = null;
 62         switch(type) {
 63         case 1:
 64             conf.put("isBase64", "false");
 65             conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("imageMaxSize")));
 66             conf.put("allowFiles", this.getArray("imageAllowFiles"));
 67             conf.put("fieldName", this.jsonConfig.getString("imageFieldName"));
 68             savePath = this.jsonConfig.getString("imagePathFormat");
 69             break;
 70         case 2:
 71             conf.put("filename", "scrawl");
 72             conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("scrawlMaxSize")));
 73             conf.put("fieldName", this.jsonConfig.getString("scrawlFieldName"));
 74             conf.put("isBase64", "true");
 75             savePath = this.jsonConfig.getString("scrawlPathFormat");
 76             break;
 77         case 3:
 78             conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("videoMaxSize")));
 79             conf.put("allowFiles", this.getArray("videoAllowFiles"));
 80             conf.put("fieldName", this.jsonConfig.getString("videoFieldName"));
 81             savePath = this.jsonConfig.getString("videoPathFormat");
 82             break;
 83         case 4:
 84             conf.put("isBase64", "false");
 85             conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("fileMaxSize")));
 86             conf.put("allowFiles", this.getArray("fileAllowFiles"));
 87             conf.put("fieldName", this.jsonConfig.getString("fileFieldName"));
 88             savePath = this.jsonConfig.getString("filePathFormat");
 89             break;
 90         case 5:
 91             conf.put("filename", "remote");
 92             conf.put("filter", this.getArray("catcherLocalDomain"));
 93             conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("catcherMaxSize")));
 94             conf.put("allowFiles", this.getArray("catcherAllowFiles"));
 95             conf.put("fieldName", this.jsonConfig.getString("catcherFieldName") + "[]");
 96             savePath = this.jsonConfig.getString("catcherPathFormat");
 97             break;
 98         case 6:
 99             conf.put("allowFiles", this.getArray("fileManagerAllowFiles"));
100             conf.put("dir", this.jsonConfig.getString("fileManagerListPath"));
101             conf.put("count", Integer.valueOf(this.jsonConfig.getInt("fileManagerListSize")));
102             break;
103         case 7:
104             conf.put("allowFiles", this.getArray("imageManagerAllowFiles"));
105             conf.put("dir", this.jsonConfig.getString("imageManagerListPath"));
106             conf.put("count", Integer.valueOf(this.jsonConfig.getInt("imageManagerListSize")));
107         }
108 
109         conf.put("savePath", savePath);
110         conf.put("rootPath", this.rootPath);
111         return conf;
112     }
113 
114     private void initEnv() throws FileNotFoundException, IOException {
115         File file = new File(this.originalPath);
116         if(!file.isAbsolute()) {
117             file = new File(file.getAbsolutePath());
118         }
119 
120         this.parentPath = file.getParent();
121         String configContent = this.readFile(this.getConfigPath());
122 
123         try {
124             JSONObject e = new JSONObject(configContent);
125             this.jsonConfig = e;
126         } catch (Exception var4) {
127             this.jsonConfig = null;
128         }
129 
130     }
131     
132     private String getConfigPath() {
133         return this.parentPath + File.separator + "config.json";
134     }
135 
136     private String[] getArray(String key) {
137         JSONArray jsonArray = this.jsonConfig.getJSONArray(key);
138         String[] result = new String[jsonArray.length()];
139         int i = 0;
140 
141         for(int len = jsonArray.length(); i < len; ++i) {
142             result[i] = jsonArray.getString(i);
143         }
144 
145         return result;
146     }
147 
148     private String readFile(String path) throws IOException {
149         StringBuilder builder = new StringBuilder();
150 
151         try {
152             InputStreamReader reader = new InputStreamReader(new FileInputStream(path), "UTF-8");
153             BufferedReader bfReader = new BufferedReader(reader);
154             String tmpContent = null;
155 
156             while((tmpContent = bfReader.readLine()) != null) {
157                 builder.append(tmpContent);
158             }
159 
160             bfReader.close();
161         } catch (UnsupportedEncodingException var6) {
162             ;
163         }
164 
165         return this.filter(builder.toString());
166     }
167 
168     private String filter(String input) {
169         return input.replaceAll("/\\*[\\s\\S]*?\\*/", "");
170     }
171 }

 

 

其中   

    private String getConfigPath() {
        return this.parentPath + File.separator + "config.json";
    }

这方法是拼全config.json的绝对路径,但是parentPath是controller.jsp 的目录路径,所以限制config.json 必须和controller.jsp在同一个目录下。当用spring或者其他代替controller.jsp时,就会找不到这个json文件。

所以这个地方我直接改为

   //修改
    private String getConfigPath() {
        return this.rootPath + File.separator + "WEB-INF" + File.separator + "classes"+File.separator + "config.json";
    }

 当然这个地方您可以随意发挥。

再者,关于上传文件路径配置问题,在源码中下载图片的类是BinaryUploader,

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package com.baidu.ueditor.upload;
 7 
 8 import com.baidu.ueditor.PathFormat;
 9 import com.baidu.ueditor.define.BaseState;
10 import com.baidu.ueditor.define.FileType;
11 import com.baidu.ueditor.define.State;
12 import org.apache.commons.fileupload.FileItemIterator;
13 import org.apache.commons.fileupload.FileItemStream;
14 import org.apache.commons.fileupload.FileUploadException;
15 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
16 import org.apache.commons.fileupload.servlet.ServletFileUpload;
17 
18 import javax.servlet.http.HttpServletRequest;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.Arrays;
22 import java.util.List;
23 import java.util.Map;
24 
25 public class BinaryUploader {
26     public BinaryUploader() {
27     }
28 
29     public static final State save(HttpServletRequest request, Map<String, Object> conf) {
30         FileItemStream fileStream = null;
31         boolean isAjaxUpload = request.getHeader("X_Requested_With") != null;
32         if(!ServletFileUpload.isMultipartContent(request)) {
33             return new BaseState(false, 5);
34         } else {
35             ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
36             if(isAjaxUpload) {
37                 upload.setHeaderEncoding("UTF-8");
38             }
39 
40             try {
41                 for(FileItemIterator e = upload.getItemIterator(request); e.hasNext(); fileStream = null) {
42                     fileStream = e.next();
43                     if(!fileStream.isFormField()) {
44                         break;
45                     }
46                 }
47 
48                 if(fileStream == null) {
49                     return new BaseState(false, 7);
50                 } else {
51                     String savePath = (String)conf.get("savePath");
52                     String originFileName = fileStream.getName();
53                     String suffix = FileType.getSuffixByFilename(originFileName);
54                     originFileName = originFileName.substring(0, originFileName.length() - suffix.length());
55                     savePath = savePath + suffix;
56                     long maxSize = ((Long)conf.get("maxSize")).longValue();
57                     if(!validType(suffix, (String[])conf.get("allowFiles"))) {
58 
59                         return new BaseState(false, 8);
60 
61                     } else {
62 
63                         savePath = PathFormat.parse(savePath, originFileName);
64                         String physicalPath = (String)conf.get("rootPath") + savePath;
65                         InputStream is = fileStream.openStream();
66                         State storageState = StorageManager.saveFileByInputStream(is, physicalPath, maxSize);
67                         is.close();
68                         if(storageState.isSuccess()) {
69                             storageState.putInfo("url", PathFormat.format(savePath));
70                             storageState.putInfo("type", suffix);
71                             storageState.putInfo("original", originFileName + suffix);
72                         }
73                         return storageState;
74                     }
75                 }
76             } catch (FileUploadException var14) {
77                 return new BaseState(false, 6);
78             } catch (IOException var15) {
79                 return new BaseState(false, 4);
80             }
81         }
82     }
83 
84     private static boolean validType(String type, String[] allowTypes) {
85         List list = Arrays.asList(allowTypes);
86         return list.contains(type);
87     }
88 }

在第64行中,String physicalPath = (String)conf.get("rootPath") + savePath; 就是上传图片最后的路径。其中rootPath是根路径,savePath是自定义的图片保存路径(imagePathFormat对应的值),在源码中rootPath已被限制为网站根目录,所以在这里需要改变为自定义的路径。

其中ConfigManager类中第109,110这里传入的路径字符串,只需将这改为

   conf.put("savePath", savePath);
        conf.put("rootPath", this.jsonConfig.getString("uploadRoot"));

就可以了。

 

最后,controller.jsp的替代方法:

 

利用拦截器:

 1 package com.imp.filter;
 2 
 3 import com.baidu.ueditor.ActionEnter;
 4 
 5 import javax.servlet.*;
 6 import javax.servlet.annotation.WebFilter;
 7 import javax.servlet.http.HttpServletRequest;
 8 import javax.servlet.http.HttpServletResponse;
 9 import java.io.IOException;
10 import java.util.logging.Logger;
11 
12 /**
13  * Created by (IMP)郑和明
14  * Date is 2016/12/26
15  *
16  * UEditor controller.jsp 拦截器
17  *
18  * 初始化 config,json
19  *
20  */
21 @WebFilter(filterName = "UEditorFilter",urlPatterns = "/ueditor/jsp/controller.jsp")
22 public class UEditorFilter implements Filter {
23     private FilterConfig config;
24 
25     public void destroy() {
26 
27     }
28 
29     public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
30 
31         HttpServletRequest request= (HttpServletRequest) req;
32         HttpServletResponse response= (HttpServletResponse) resp;
33         request.setCharacterEncoding("utf-8");
34         response.setHeader("Content-Type", "text/html");
35         String rootPath= config.getServletContext().getRealPath("/");
36         Logger.getLogger("imp").info(rootPath);
37         String res=new ActionEnter(request, rootPath).exec();
38         response.getWriter().write(res);
39 
40     }
41     public void init(FilterConfig config) throws ServletException {
42         this.config=config;
43     }
44 
45 }

 

或者

String mvc也可以(前提拦截所有jsp请求,然后自定义controller)(代码(略))

 

代码 github 地址  https://github.com/zhenghe1993/UEditor