1. 程式人生 > >百度UEditor自定義上傳檔案儲存路徑

百度UEditor自定義上傳檔案儲存路徑

這是基於SSM專案中,使用freemaker加UEditor富文字編輯器修改的,不過使用與JSP的UEditor大同小異,修改後的功能是可以配置上傳圖片、檔案、塗鴉等的儲存路徑,而不是預設地儲存在專案路徑下。

首先,增加ueditor.properties配置檔案,內容為:

#上傳檔案儲存路徑
ueditor.imagePath=F:/jblog/

修改UEditorController,如果是使用JSP頁面的,對應修改controller.jsp:
原本的UEditorController為:

@Controller
@RequestMapping("/static/ueditor"
) public class UEditorController { @RequestMapping("/jsp/controller") public void writePage(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding( "utf-8" ); response.setHeader("Content-Type" , "text/html"); String rootPath = request.getSession().getServletContext().getRealPath("/"
); response.getWriter().write(new ActionEnter(request, rootPath).exec()); } }

修改後:

@Controller
@RequestMapping("/static/ueditor")
public class UEditorController {

    private static String saveRootPath;

    static {
        try {
            Properties prop = new Properties();
            InputStream inStream = (new
DefaultResourceLoader()).getResource("classpath:ueditor.properties").getInputStream(); prop.load(inStream); saveRootPath = prop.getProperty("ueditor.imagePath"); } catch (Exception e) { throw new RuntimeException("從ueditor.properties配置檔案中獲取ueditor圖片儲存位置失敗", e); } } @RequestMapping("/jsp/controller") public void writePage(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding( "utf-8" ); response.setHeader("Content-Type" , "text/html"); String rootPath = request.getSession().getServletContext().getRealPath("/"); response.getWriter().write(new ActionEnter(request, rootPath, saveRootPath).exec()); } }

此時,會發現new ActionEnter(request, rootPath, saveRootPath)報錯,是因為ActionEnter構造器只有兩個引數的,這裡需要修改ueditor.jar中的類。

修改ConfigManager類:

//增加欄位saveRootPath
...
private String saveRootPath = null;
...
//構造器增加引數saveRootPath,
//並在構造器中對saveRootPath賦值
private ConfigManager(String rootPath, String contextPath, String saveRootPath, String uri) throws FileNotFoundException, IOException {
        rootPath = rootPath.replace("\\", "/");
        this.saveRootPath = saveRootPath;
        this.rootPath = rootPath;
        this.contextPath = contextPath;
        if (contextPath.length() > 0) {
            this.originalPath = this.rootPath + uri.substring(contextPath.length());
        } else {
            this.originalPath = this.rootPath + uri;
        }

        this.initEnv();
}
//getInstance方法引數saveRootPath,呼叫修改後的構造器
public static ConfigManager getInstance(String rootPath, String contextPath, String saveRootPath, String uri) {
        try {
            return new ConfigManager(rootPath, contextPath, saveRootPath, uri);
        } catch (Exception var4) {
            return null;
        }
}
...
//把saveRootPath設定到config中
public Map<String, Object> getConfig(int type) {
        Map<String, Object> conf = new HashMap();
        String savePath = null;
        ...
        conf.put("savePath", savePath);
        conf.put("rootPath", this.rootPath);
        conf.put("saveRootPath", this.saveRootPath);
        return conf;
    }

修改ActionEnter類:

    ...
    //增加欄位saveRootPath
    private String saveRootPath = null;
    ...
    //修改ActionEnter構造器,呼叫修改後的ConfigManager.getInstance方法
    public ActionEnter(HttpServletRequest request, String rootPath, String saveRootPath) {
        this.request = request;
        this.rootPath = rootPath;
        this.saveRootPath = saveRootPath;
        this.actionType = request.getParameter("action");
        this.contextPath = request.getContextPath();
        this.configManager = ConfigManager.getInstance(this.rootPath, this.contextPath, this.saveRootPath, request.getRequestURI());
    }

修改BinaryUploader類:

public class BinaryUploader {
    public BinaryUploader() {
    }

    public static final State save(HttpServletRequest request, Map<String, Object> conf) {
        try {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request;
            MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());
            String savePath = (String)conf.get("savePath");
            String originFileName = multipartFile.getOriginalFilename();
            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[])((String[])conf.get("allowFiles")))) {
                return new BaseState(false, 8);
            } else {
                savePath = PathFormat.parse(savePath, originFileName);
                int index = savePath.lastIndexOf('/');
                String saveRootPath = (String)conf.get("saveRootPath");
                String physicalPath = saveRootPath + savePath.substring(0, index);
                File targetFile = new File(physicalPath);
                if (!targetFile.exists()) {
                    targetFile.mkdirs();
                }

                State storageState = StorageManager.saveFileByInputStream(multipartFile.getInputStream(), saveRootPath + savePath, maxSize);
                if (storageState.isSuccess()) {
                    storageState.putInfo("url", PathFormat.format(savePath));
                    storageState.putInfo("type", suffix);
                    storageState.putInfo("original", originFileName + suffix);
                }

                return storageState;
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
            return new BaseState(false, 4);
        }
    }

    private static boolean validType(String type, String[] allowTypes) {
        List<String> list = Arrays.asList(allowTypes);
        return list.contains(type);
    }
}

到這裡完成了對圖片、視訊、檔案的儲存路徑的修改,如果需要用到塗鴉的功能,還需要修改Base64Uploader類:

    public static State save(String content, Map<String, Object> conf) {
        byte[] data = decode(content);
        long maxSize = ((Long)conf.get("maxSize")).longValue();
        if (!validSize(data, maxSize)) {
            return new BaseState(false, 1);
        } else {
            String suffix = FileType.getSuffix("JPG");
            String savePath = PathFormat.parse((String)conf.get("savePath"), (String)conf.get("filename"));
            savePath = savePath + suffix;
            String physicalPath = (String)conf.get("saveRootPath") + savePath;
            State storageState = StorageManager.saveBinaryFile(data, physicalPath);
            if (storageState.isSuccess()) {
                storageState.putInfo("url", PathFormat.format(savePath));
                storageState.putInfo("type", suffix);
                storageState.putInfo("original", "");
            }

            return storageState;
        }
    }

完成了上傳檔案的儲存設定後,圖片還不能回顯,在spring mvc配置檔案中增加配置:

    <context:property-placeholder location="classpath:ueditor.properties" />
    <mvc:resources  mapping="/ueditor/upload/**" location= "file:${ueditor.imagePath}/ueditor/upload/" />

配置檔案config.json內容為:

/* 上傳圖片配置項 */
    "imageActionName": "uploadimage", /* 執行上傳圖片的action名稱 */
    "imageFieldName": "upfile", /* 提交的圖片表單名稱 */
    "imageMaxSize": 2048000, /* 上傳大小限制,單位B */
    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上傳圖片格式顯示 */
    "imageCompressEnable": true, /* 是否壓縮圖片,預設是true */
    "imageCompressBorder": 1600, /* 圖片壓縮最長邊限制 */
    "imageInsertAlign": "none", /* 插入的圖片浮動方式 */
    "imageUrlPrefix": "/admin", /* 圖片訪問路徑字首 */
    "imagePathFormat": "/ueditor/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}"
    ......

修改後的效果為:
圖1

圖2

圖3

還有其中截圖功能不能使用的問題尚未解決
圖4
點選截圖後,提示需要安裝截圖外掛,安裝完成後點選截圖依舊出現該介面,再火狐,谷歌,還有Windows10自帶的瀏覽器都是如此,只有IE可以調用出截圖功能,可是會出現錯誤:
圖5

異常資訊為:

org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:168)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:142)
    at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1104)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:936)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2555)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2544)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:362)
    at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:158)
    ... 50 more
Caused by: org.apache.commons.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
    at org.apache.commons.fileupload.MultipartStream.readHeaders(MultipartStream.java:540)
    at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:1038)
    at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.hasNext(FileUploadBase.java:1106)
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:339)
    ... 52 more

看起來是流中斷了,此問題未能解決。