UEditor WEB-INF目录访问与自定义上传

UEditor很好用,但是它的图片默认是上传到项目中,重新部署项目后之前的图片全会被删掉(坑爹),为了实现把图片传到其他地方,如阿里云的OSS(不是打广告),可以进行以下改造实现。

后端配置

  1. 下载的包里面./jsp/lib有5个jar包,其中commons-*.jarjson.jar可通过maven下载,ueditor-*.jarMaven上有但是不是官方上传的,所以我手动导入到项目
  2. 把整个包复制到项目资源目录,如放到WEB-INF目录下还要通过一下特殊配置,如直接放到webapp目录下可参考官方文档
  3. 假设插件放置位置为WEB-INF/assets/plugins/ueditor,因为WEB-INF目录下内容不能直接访问,ueditor/jsp/controller.jsp是无法配置的,所以需要通过Spring Mvc中的Controller转发访问
  4. 项目新建一个Controller并配置RequestMapping
    Controller
@Controller
@RequestMapping("/ueditor")
public class UEditorController {

    /**
     * UEditor 入口
     *
     * @return
     */
    @RequestMapping("/controller")
    public String controller() {
        return "common/_ueditor";
    }
}

common/_ueditor.jsp

<jsp:forward page ="/WEB-INF/assets/plugins/ueditor/jsp/controller.jsp" />
  1. 在要调用ueditor的页面配置ueditor
<!--配置文件-->
<script src="<%=request.getContextPath()%>/assets/plugins/ueditor/ueditor.config.js"></script>
 <!--必须放到ueditor.config.js之后,ueditor.all.mim.js之前,路径根据实际情况修改-->
<script>
    window.UEDITOR_CONFIG.serverUrl = "<%=request.getContextPath()%>/ueditor/controller"
</script>
<!-- 编辑器源码文件 -->
<script src="<%=request.getContextPath()%>/assets/plugins/ueditor/ueditor.all.min.js"></script>
  1. 到此ueditor的后端配置完成,调用方法可参考官方文档

改造

1.重写ActionEnter类

import com.baidu.ueditor.ConfigManager;
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 javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * Created by GustinLau on 2017-05-11.
 */
public class ActionEnter extends com.baidu.ueditor.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) {
        super(request, rootPath);
        this.request = request;
        this.rootPath = rootPath;
        this.actionType = request.getParameter("action");
        this.contextPath = request.getContextPath();
        this.configManager = ConfigManager.getInstance(this.rootPath, this.contextPath, request.getRequestURI());
    }

    @Override
    public String invoke() {
        if(this.actionType != null && ActionMap.mapping.containsKey(this.actionType)) {
            if(this.configManager != null && this.configManager.valid()) {
                State state = null;
                int actionCode = ActionMap.getType(this.actionType);
                Map<String, Object> 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 = this.getStartIndex();
                        state = (new FileManager(conf)).listFile(start);
                }

                return state.toJSONString();
            } else {
                return (new BaseState(false, 102)).toJSONString();
            }
        } else {
            return (new BaseState(false, 101)).toJSONString();
        }
    }

}

其中case 4中的Uploader需要重写

2.重写Uploader

import com.baidu.ueditor.define.State;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * Created by GustinLau on 2017-05-11.
 */
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;
        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;
    }
}

其中Base64UploaderBinaryUploader需要重写

3.重写Base64Uploader,主要用于涂鸦功能

import com.baidu.ueditor.PathFormat;
import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.FileType;
import com.baidu.ueditor.define.State;
import com.xiaosuokeji.feelschool.admin.util.OssUtils;
import org.apache.commons.codec.binary.Base64;

import java.io.ByteArrayInputStream;
import java.util.Map;

/**
 * Created by GustinLau on 2017-05-11.
 */
public class 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;
            
            //自定义处理部分
            //将byte[]转换成输入流
            ByteArrayInputStream is = new ByteArrayInputStream(data);
            //图片上传到阿里云OSS服务器,自己写的工具类
            Map result = OssUtils.ueditorUpload(is, savePath);
            //构造对应的Stage让UEditor读取
            State storageState = new BaseState((boolean) result.get("status"));
            if (storageState.isSuccess()) {
                storageState.putInfo("url", (String) result.get("url"));
                storageState.putInfo("type", suffix);
                storageState.putInfo("original", "");
            }

            return storageState;
        }
    }

    private static byte[] decode(String content) {
        return Base64.decodeBase64(content);
    }

    private static boolean validSize(byte[] data, long length) {
        return (long) data.length <= length;
    }
}

4.重写BinaryUploader主要用于上传图片

import com.baidu.ueditor.PathFormat;
import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.FileType;
import com.baidu.ueditor.define.State;
import com.xiaosuokeji.feelschool.admin.util.OssUtils;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Created by GustinLau on 2017-05-11.
 */
public class BinaryUploader {

    public static final State save(HttpServletRequest request, Map<String, Object> conf) {
        MultipartFile multipartFile = null;
        boolean isAjaxUpload = request.getHeader("X_Requested_With") != null;
        if (!ServletFileUpload.isMultipartContent(request)) {
            return new BaseState(false, 5);
        } else {
            ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
            if (isAjaxUpload) {
                upload.setHeaderEncoding("UTF-8");
            }
            //自定义处理部分
            try {
                //request获取MultipartFile对象
                MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
                multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());

                if (multipartFile == null) {
                    return new BaseState(false, 7);
                } else {
                    //重命名
                    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;
                    if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
                        return new BaseState(false, 8);
                    } else {
                        savePath = PathFormat.parse(savePath, originFileName);
                        //获取输入流
                        InputStream is = multipartFile.getInputStream();
                        //上传到阿里云OSS
                        Map result = OssUtils.ueditorUpload(is, savePath);
                        //构造State
                        State storageState = new BaseState((boolean) result.get("status"));
                        is.close();
                        if (storageState.isSuccess()) {
                            storageState.putInfo("url", (String) result.get("url"));
                            storageState.putInfo("type", suffix);
                            storageState.putInfo("original", originFileName + suffix);
                        }

                        return storageState;
                    }
                }
            } catch (IOException e) {
                return new BaseState(false, 4);
            }
        }
    }

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

5.将在WEB-INF/assets/plugins/ueditor/jsp/controller.jsp中的ActionEnter换自己重写的ActionEnter

依赖

<!--ueditor-->
<dependency>
    <groupId>com.baidu</groupId>
    <artifactId>ueditor</artifactId>
    <version>1.1.2</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/ueditor-1.1.2.jar</systemPath>
</dependency>
<!--json-->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160212</version>
</dependency>

 <dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>
<!--fileupload-->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

备注

记得在spring.xml中配置MultipartResolver

<!-- 配置MultipartResolver 用于文件上传 使用spring的CommonsMultipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="UTF-8"/>
    <property name="maxUploadSize" value="${file.maxSize}"/>
    <property name="resolveLazily" value="true"/>
</bean>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容