ueditor文件上传研究

xiaoxiao2021-02-27  290

之前写过一版本的ueditor的使用方式,感觉后来ueditor升级很快,转眼间又升级了,今天有一个人问这块相关的问题,正好又熟悉下。      首先最基本的用法我就不讲了,只讲文件上传的这块。      首先,文件上传这块和之前的变化很大,先慢慢的讲讲用法。      1. java版本的在jsp目录的文件结构如下:                         从这地方可以看出来,有一个controller.jsp, 一个config.json,一堆jar文件, 这个和之前版本是不一致的。         2. maven工程的jar包的引用         如果没有使用jar包,很容易,直接copy文件就可以,但是maven的方式,这个jar又在网上没有,索幸maven提供了system方式的依赖方式:         Xml代码   < dependency>                < groupId> com.baidu.ueditor </groupId >                < artifactId> ueditor </artifactId >                < version> 1.1.1 </version >                < scope> system </scope >                < systemPath> ${basedir}/ src/main/webapp /WEB-INF/lib/ ueditor-1.1.1.jar </systemPath >            </ dependency>             maven的jar包的放置位置如下:                   其他的jar我就不多讲了,都很容易找。         3. controller.jsp文件阅读          Html代码   <%@ page language="java" contentType="text/html; charset=UTF-8"       import="com.baidu.ueditor.ActionEnter"       pageEncoding="UTF-8"%>   <%@ page trimDirectiveWhitespaces="true" %>   <%          request.setCharacterEncoding( "utf-8" );       response.setHeader("Content-Type" , "text/html");              String rootPath = application.getRealPath( "/" );              out.write( new ActionEnter( request, rootPath ).exec() );          %>             从代码来看,rootPath其实就是项目的根路径,构建了ActionEnter,并调用了exec函数。        我们来看下ActionEnter的代码:         Java代码   package com.baidu.ueditor;      import com.baidu.ueditor.define.ActionMap;   import com.baidu.ueditor.define.BaseState;   import com.baidu.ueditor.define.State;   import com.baidu.ueditor.hunter.FileManager;   import com.baidu.ueditor.hunter.ImageHunter;   import com.baidu.ueditor.upload.Uploader;   import java.util.Map;   import javax.servlet.http.HttpServletRequest;   import org.json.JSONObject;      public class ActionEnter   {     private HttpServletRequest request = null;        private String rootPath = null;     private String contextPath = null;        private String actionType = null;        private ConfigManager configManager = null;        public ActionEnter(HttpServletRequest request, String rootPath)     {       this.request = request;       this.rootPath = rootPath;       // 对action进行赋值。       this.actionType = request.getParameter("action");       this.contextPath = request.getContextPath();       // 构建configManager类       this.configManager = ConfigManager.getInstance(this.rootPath, this.contextPath, request.getRequestURI());     }        public String exec()     {       // 这个是处理jsonp的形式,一般都是不跨域的。       String callbackName = this.request.getParameter("callback");          if (callbackName != null)       {         if (!validCallbackName(callbackName)) {           return new BaseState(false401).toJSONString();         }            return callbackName + "(" + invoke() + ");";       }          return invoke();     }        public String invoke()     {       // 判断action是否合法,如果不合法返回一个非法状态       if ((this.actionType == null) || (!ActionMap.mapping.containsKey(this.actionType))) {         return new BaseState(false101).toJSONString();       }      // 如果找不到configManager也报错       if ((this.configManager == null) || (!this.configManager.valid())) {         return new BaseState(false102).toJSONString();       }          State state = null;          // 取得actionCode       int actionCode = ActionMap.getType(this.actionType);          Map conf = null;          switch (actionCode)       {       case 0:         return this.configManager.getAllConfig().toString();       case 1:       case 2:       case 3:       case 4:         // 处理上传文件         conf = this.configManager.getConfig(actionCode);         state = new Uploader(this.request, conf).doExec();         break;       case 5:         conf = this.configManager.getConfig(actionCode);         String[] list = this.request.getParameterValues((String)conf.get("fieldName"));         // 处理在线编辑         state = new ImageHunter(conf).capture(list);         break;       case 6:       case 7:         conf = this.configManager.getConfig(actionCode);         int start = getStartIndex();         // 处理文件list         state = new FileManager(conf).listFile(start);       }          return state.toJSONString();     }        public int getStartIndex()     {       String start = this.request.getParameter("start");       try       {         return Integer.parseInt(start); } catch (Exception e) {       }       return 0;     }        public boolean validCallbackName(String name)     {       if (name.matches("^[a-zA-Z_]+[\\w0-9_]*$")) {         return true;       }          return false;     }   }             我们慢慢的来看这个函数:首先在构造函数里面调用了request.getContextPath()和request.getRequestURI()函数。         假设我们的项目的contextPath为:test,那么下面两个函数的返回值则如下:   request.getContextPath                   /test    request.getRequestURI           /test/resources/ueditor/jsp/controller.jsp    我们还是先来看下ConfigManager类吧。     Java代码   package com.baidu.ueditor;      import java.io.BufferedReader;   import java.io.File;   import java.io.FileInputStream;   import java.io.FileNotFoundException;   import java.io.IOException;   import java.io.InputStreamReader;   import java.io.UnsupportedEncodingException;   import java.util.HashMap;   import java.util.Map;   import org.json.JSONArray;   import org.json.JSONObject;      public final class ConfigManager   {     private final String rootPath;     private final String originalPath;     private final String contextPath;     private static final String configFileName = "config.json";     private String parentPath = null;     private JSONObject jsonConfig = null;     private static final String SCRAWL_FILE_NAME = "scrawl";     private static final String REMOTE_FILE_NAME = "remote";        private ConfigManager(String rootPath, String contextPath, String uri)       throws FileNotFoundException, IOException     {       rootPath = rootPath.replace("\\", "/");          this.rootPath = rootPath;       this.contextPath = contextPath;       // 这个地方要特别注意,originalPath其实就是controller.jsp所在的路径       if (contextPath.length() > 0)         this.originalPath = (this.rootPath + uri.substring(contextPath.length()));       else {         this.originalPath = (this.rootPath + uri);       }          initEnv();     }        public static ConfigManager getInstance(String rootPath, String contextPath, String uri)     {       try       {         return new ConfigManager(rootPath, contextPath, uri); } catch (Exception e) {       }       return null;     }        public boolean valid()     {       return this.jsonConfig != null;     }        public JSONObject getAllConfig()     {       return this.jsonConfig;     }        public Map<String, Object> getConfig(int type)     {       Map conf = new HashMap();       String savePath = null;       // 根据不同的code来解析config.json的配置文件       switch (type)       {       case 4:         conf.put("isBase64""false");         conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("fileMaxSize")));         conf.put("allowFiles", getArray("fileAllowFiles"));         conf.put("fieldName"this.jsonConfig.getString("fileFieldName"));         savePath = this.jsonConfig.getString("filePathFormat");         break;       case 1:         conf.put("isBase64""false");         conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("imageMaxSize")));         conf.put("allowFiles", getArray("imageAllowFiles"));         conf.put("fieldName"this.jsonConfig.getString("imageFieldName"));         savePath = this.jsonConfig.getString("imagePathFormat");         break;       case 3:         conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("videoMaxSize")));         conf.put("allowFiles", getArray("videoAllowFiles"));         conf.put("fieldName"this.jsonConfig.getString("videoFieldName"));         savePath = this.jsonConfig.getString("videoPathFormat");         break;       case 2:         conf.put("filename""scrawl");         conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("scrawlMaxSize")));         conf.put("fieldName"this.jsonConfig.getString("scrawlFieldName"));         conf.put("isBase64""true");         savePath = this.jsonConfig.getString("scrawlPathFormat");         break;       case 5:         conf.put("filename""remote");         conf.put("filter", getArray("catcherLocalDomain"));         conf.put("maxSize", Long.valueOf(this.jsonConfig.getLong("catcherMaxSize")));         conf.put("allowFiles", getArray("catcherAllowFiles"));         conf.put("fieldName"this.jsonConfig.getString("catcherFieldName") + "[]");         savePath = this.jsonConfig.getString("catcherPathFormat");         break;       case 7:         conf.put("allowFiles", getArray("imageManagerAllowFiles"));         conf.put("dir"this.jsonConfig.getString("imageManagerListPath"));         conf.put("count", Integer.valueOf(this.jsonConfig.getInt("imageManagerListSize")));         break;       case 6:         conf.put("allowFiles", getArray("fileManagerAllowFiles"));         conf.put("dir"this.jsonConfig.getString("fileManagerListPath"));         conf.put("count", Integer.valueOf(this.jsonConfig.getInt("fileManagerListSize")));       }          conf.put("savePath", savePath);       conf.put("rootPath"this.rootPath);          return conf;     }        // 加载config.json配置文件     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 = readFile(getConfigPath());       try       {         JSONObject jsonConfig = new JSONObject(configContent);         this.jsonConfig = jsonConfig;       } catch (Exception e) {         this.jsonConfig = null;       }     }        private String getConfigPath()     {       return this.parentPath + File.separator + "config.json";     }        private String[] getArray(String key)     {       JSONArray jsonArray = this.jsonConfig.getJSONArray(key);       String[] result = new String[jsonArray.length()];          int i = 0for (int len = jsonArray.length(); i < len; i++) {         result[i] = jsonArray.getString(i);       }          return result;     }           // 读取config.json里面的内容     private String readFile(String path)       throws IOException     {       StringBuilder builder = new StringBuilder();       try       {         InputStreamReader reader = new InputStreamReader(new FileInputStream(path), "UTF-8");         BufferedReader bfReader = new BufferedReader(reader);            String tmpContent = null;            while ((tmpContent = bfReader.readLine()) != null) {           builder.append(tmpContent);         }            bfReader.close();       }       catch (UnsupportedEncodingException localUnsupportedEncodingException)       {       }          return filter(builder.toString());     }        private String filter(String input)     {       return input.replaceAll("/\\*[\\s\\S]*?\\*/""");     }   }           我们再来看 Uploader函数,其实很简单:     Java代码   package com.baidu.ueditor.upload;      import com.baidu.ueditor.define.State;   import java.util.Map;   import javax.servlet.http.HttpServletRequest;      public class Uploader   {     private HttpServletRequest request = null;     private Map<String, Object> conf = null;        public Uploader(HttpServletRequest request, Map<String, Object> conf) {       this.request = request;       this.conf = conf;     }        public final State doExec() {       String filedName = (String)this.conf.get("fieldName");       State state = null;          if ("true".equals(this.conf.get("isBase64")))         state = Base64Uploader.save(this.request.getParameter(filedName),            this.conf);       else {         state = BinaryUploader.save(this.request, this.conf);       }          return state;     }   }             这个很好理解,我们接着来看BinaryUploader类:       Java代码   package com.baidu.ueditor.upload;      import com.baidu.ueditor.PathFormat;   import com.baidu.ueditor.define.BaseState;   import com.baidu.ueditor.define.FileType;   import com.baidu.ueditor.define.State;   import java.io.IOException;   import java.io.InputStream;   import java.util.Arrays;   import java.util.List;   import java.util.Map;   import javax.servlet.http.HttpServletRequest;   import org.apache.commons.fileupload.FileItemIterator;   import org.apache.commons.fileupload.FileItemStream;   import org.apache.commons.fileupload.FileUploadException;   import org.apache.commons.fileupload.disk.DiskFileItemFactory;   import org.apache.commons.fileupload.servlet.ServletFileUpload;      public class BinaryUploader   {     // 使用fileupload来处理文件上传     public static final State save(HttpServletRequest request, Map<String, Object> conf)     {       FileItemStream fileStream = null;       boolean isAjaxUpload = request.getHeader("X_Requested_With") != null;          if (!ServletFileUpload.isMultipartContent(request)) {         return new BaseState(false5);       }          ServletFileUpload upload = new ServletFileUpload(         new DiskFileItemFactory());          if (isAjaxUpload) {         upload.setHeaderEncoding("UTF-8");       }       try       {         FileItemIterator iterator = upload.getItemIterator(request);            while (iterator.hasNext()) {           fileStream = iterator.next();              if (!fileStream.isFormField())             break;           fileStream = null;         }            if (fileStream == null) {           return new BaseState(false7);         }            String savePath = (String)conf.get("savePath");         String originFileName = fileStream.getName();         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(false8);         }            savePath = PathFormat.parse(savePath, originFileName);            String physicalPath = (String)conf.get("rootPath") + savePath;            // 调用存储类来处理文件存储         InputStream is = fileStream.openStream();         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 (FileUploadException e) {         return new BaseState(false6);       } catch (IOException localIOException) {       }       return new BaseState(false4);     }        private static boolean validType(String type, String[] allowTypes) {       List list = Arrays.asList(allowTypes);          return list.contains(type);     }   }               StorageManager我们就不看了,无非就是做一些文件存储的一些事情,下面我们来分析下这种实现方式的问题。         最后我稍微总结下看这个代码得收获和对作者的建议:   从这个地方来看,无法将图片放置在外部路径,因为这种实现就决定了只能放到项目路径下,这个最大的问题就是,有可能不小心,重新上下线,内容全部丢了。  从实现来看,大量的使用静态调用,基本上无法二次开发,不能灵活的继承它来处理个性化的东西,比如如果存储到fastDFS里面,这个就需要改里面的代码,不能通过扩展的方式来进行 config.json里面的配置项转换的时候,进行了重命名,这个地方就要求读者要记两个变量名,比如:imagePathFormat变成了savePath, 感觉好像挺好理解,但是这种明显不是好的方式,如果里面存在一个这个逻辑,最好显式的说明,而不是硬编码 源代码不开放,无法进行扩展和修改,建议作者开发这个jar到github里面,社区一块维护 
转载请注明原文地址: https://www.6miu.com/read-3523.html

最新回复(0)