kindEditor和wangEditor的使用

开发一个项目的时候,有一块地方突然需要使用到富文本编辑器,之前也用过一些编辑器,例如wangEditor和百度的Editior,综合来说,我更喜欢简洁型的,wangEditor就非常不错,简洁大方。百度的Editior给人看起来有种太华丽的感觉,虽然都可以配置自己需要的使用插件,但是还是喜欢wangEditor。

今天这里要说到的是wangEditor和kindEditor。

首先来说:kindEditor

官网下载

下载下来后解压,解压后重命名文件夹名称为kindeditor。在Javaweb项目中如何使用,请看下图配置:

项目结构
说下总体的目录结构:
  1. attached: 文件的上传完的存储目录。
  2. examples: 例子。
  3. jsp: 上传用到的文件。
  4. lang: 语言包。
  5. plugins: 配置插件包。
  6. themes: 主题目录。

再下面的就是用到的主要js文件了。

项目运行的时候记得把这几个包部署进去,包在lib目录里面。

项目结构

现在可以启动tomcat,地址栏访问:http://localhost/kindeditor/kindeditor/jsp/demo.jsp

如下图是正确访问以后出现的画面:

项目结构

选择插入一张图片,成功把上传完的图片显示在文本编辑器里面

项目结构

最后查看一下这个图片所在的上传目录

项目结构

kindeditor就说到这里,上传都配置好了,后面的怎么获取值就很好办了,这里先不说了。直接下一个编辑器。

wangEditor的使用

官网下载

首先,你进入到官网,就感觉这个编辑器非常不错,简洁大方。看图所示:

项目结构

直接说在项目中如何使用吧?

复制到解压后的文件到webapp目录下

demo

这里也是整体配置开始吧:

<!-- 创建一个编辑器 -->
<script type="text/javascript">
    var E = window.wangEditor
    var editor = new E('#editor')
    
    /* 获取元素 */
    /* editor.customConfig.debug = location.href.indexOf('publishTask.html') > 0 */
    
    // 限制一次最多上传 5 张图片
    editor.customConfig.uploadImgMaxLength = 5

    // 将图片大小限制为 3M
    editor.customConfig.uploadImgMaxSize = 3 * 1024 * 1024
    
    /* 上传图片文件的参数名称 */
    editor.customConfig.uploadFileName = 'fileName'
    
    editor.customConfig.uploadImgParams = {
        //token: 'abcdef12345'   // 属性值会自动进行 encode ,此处无需 encode
    }
    
    /* 图片上传的配置 */
    editor.customConfig.uploadImgServer = '/stt/file/savePicture'  /* 上传到服务器的,不能和base64同时使用 */
    /* editor.customConfig.uploadImgShowBase64 = true  */   /* base64存储 */

    /* 创建 */
    editor.create();
    
    /* 上传监听函数 */
    editor.customConfig.uploadImgHooks = {
            before: function (xhr, editor, files) {
                // 图片上传之前触发
                // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,files 是选择的图片文件
                alert(files)
            },
            success: function (xhr, editor, result) {
                // 图片上传并返回结果,图片插入成功之后触发
                console.log(xhr)
                console.log(editor)
                console.log(result)
                // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
            },
            fail: function (xhr, editor, result) {
                // 图片上传并返回结果,但图片插入错误时触发
                alert(result)
                // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
            },
            error: function (xhr, editor) {
                // 图片上传出错时触发
                // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
                
            },
            timeout: function (xhr, editor) {
                // 图片上传超时时触发
                // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
            },

            // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
            // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
            customInsert: function (insertImg, result, editor) {
                // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
                // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果

                // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
                var url = result.url
                insertImg(url)

                // result 必须是一个 JSON 格式字符串!!!否则报错
            }
        }
    
    <!-- 获取值 -->
    document.getElementById('save').addEventListener('click', function () {
        var content = editor.txt.text();
        var title = $('input[name=title]').val();
        var description = $('input[name=description]').val();
        var score = $('input[name=score]').val();
        if(title == '' || title == null){
            alert('请输入标题');
            return false;
        }
        if(description == '' || description == null){
            alert('请输入任务简述信息');
            return false;
        }
        if(content =='' || content == null){
            alert('请输入内容信息');
            return false;
        }
        if(score =='' || score == null){
            alert('请输入积分设置数');
            return false;
        }else{
            
            $('input[name=content]').val(content);  //给隐藏表单域赋值
            
            $.post('../../task/saveTask',$('form').serialize(),function(res){
                    
                    alert(res)
            });
            
        }
    }, false);
</script>

前端代码粘贴到上面了,这里说上传那块儿的。

  1. 首先你的配置你的上传服务器的请求地址.
  2. 对上传按需做一些基本配置,如:同时上传图片的数量,大小限制,文件参数名称等。
  3. 配置好上传事件监听,成功了..失败了...上传图片但图片未返回报错等等事件最好都监听一下。
  4. 返回格式的要求。官方提供了两种。

第一种:

{
    // errno 即错误代码,0 表示没有错误。
    //       如果有错误,errno != 0,可通过下文中的监听函数 fail 拿到该错误码进行自定义处理
    errno: 0,

    // data 是一个数组,返回若干图片的线上地址
    data: [
        '图片1地址',
        '图片2地址',
        '……'
    ]
}

第二种:

// 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
    // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
    customInsert: function (insertImg, result, editor) {
        // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
        // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
         //这里说的就是第二种的情况(但是感觉第二种只能单张图传,有点麻烦,第一种能多图传。)
        // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
        var url = result.url
        insertImg(url)

        // result 必须是一个 JSON 格式字符串!!!否则报错
    }
}

好了,既然第一种要返回json格式,那就直接看后台代码吧。

这里是上传的请求控制器

@ResponseBody
    @RequestMapping(value="savePicture",method=RequestMethod.POST)
    public JSONObject savePicture(@RequestParam("fileName") MultipartFile[]  fileName,
            HttpServletRequest request){
        JSONObject obj = new JSONObject();
        
        //测试上传是否成功前写死的例子
//      String img[] =  {"http://localhost/stt/file/image/1706231708000014/2017062317080001465502.jpg/true",
//              "http://localhost/stt/file/image/1706211120000005/2017062111200000589174.jpg/true",
//              "http://localhost/stt/file/image/1706191036000002/2017061910360000275916.png/true"};
        
        try {
            String[] img = saveImgFiles(fileName);
            
            obj.put("errno", 0);
            obj.put("data", img);
        }catch (Exception e) {
            
            obj.put("errno", -1);
            obj.put("data", "上传失败!");
            
            e.printStackTrace();
        }
        
        System.out.println(obj);
        return obj;
    }

再就是保存多张图片的方法

    /**
     * 保存多张图片
     * @param product
     * @param detailImgFiles
     * @throws IOException 
     * @throws FileNotFoundException 
     */
    public String[] saveImgFiles(MultipartFile[] detailImgFiles) throws FileNotFoundException, IOException{
        
        StringBuffer sb = new StringBuffer(50);
        
        List<String> str = new ArrayList<>();
        
        for (int i = 0; i < detailImgFiles.length; i++) {
            MultipartFile file = detailImgFiles[i];
            
            if("".equals(file.getOriginalFilename())){
                continue;
            }
            
//          StringBufferUtil.append(sb,managerConf.getProductSave(),"/");
            sb.append("/base/stt/img/");
            
            FileUtil.createDirNotExists(sb.toString());
            String newFileName = newFileName(file);  //重命名文件
            sb.append(newFileName);
            
            str.add("/stt/file/image/" + newFileName +"/");  //访问图片输出流的前缀地址  + //图片存储的物理路径地址。
            
            //保存文件
            FileUtil.saveFile(detailImgFiles[i].getInputStream(), new FileOutputStream(sb.toString()));
            StringBufferUtil.clear(sb);
            
        }
        String[] img = (String[])str.toArray(new String[str.size()]);
        
        return img;
        
    }

给文件重命名方法

    /**
     * 给文件重新命名
     * @param minImgFile
     * @return
     */
    private static String newFileName(MultipartFile minImgFile){

        String filename = minImgFile.getOriginalFilename();
        String dateStr = DateUtil.getDateStr(new Date(), "yyyyMMddHHmmsssss");
        
        StringBuffer sb = new StringBuffer(20);
        sb.append(filename);
        filename = sb.replace(0, filename.lastIndexOf("."),"").toString();
        StringBufferUtil.clear(sb);
        
        sb.append(dateStr);
        for (int i = 0; i < 5; i++) {
            sb.append( (int)(Math.random() * 10));
        }
        
        sb.append(filename);
        return sb.toString();
    }//end newFileName

还有一个地方需要注意的就是文件上传到的是外部磁盘目录,我们给返回的图片要让它访问磁盘目录文件,需要用文件输出流:

    /**
     * 访问一个添加的图片
     * @param fileName
     * @param request
     * @return
     */
    @RequestMapping("/image/{fileName}/")
    public void visitImg(@PathVariable("fileName") String fileName,HttpServletResponse response){
        FileInputStream fis = null;
        StringBuffer sb = new StringBuffer(20);
        try {
//          String imgPath = StringBufferUtil.append(sb, ManagerConf.getMangerConf().getProductSave(),"/",proNo,"/",fileName).toString();

            sb.append("/base/stt/img/");
            
            FileUtil.createDirNotExists(sb.toString());
            String imgPath = sb.toString() + fileName;
            if(!FileUtil.fileExists(imgPath)){
                return;
            }
            
            ServletOutputStream os = response.getOutputStream();
            fis = new FileInputStream(imgPath);
            byte[] bs = new byte[fis.available()];
            fis.read(bs);
            os.write(bs);
            
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                if(fis != null)fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

最后,测试多图同时上传一下吧:

测试上传

需要注意的地方,返回的json数据格式如下:

{"errno":0,"data":["/stt/file/image/2017062922410001580284.jpg/","/stt/file/image/2017062922410001546426.jpg/","/stt/file/image/2017062922410001522021.gif/"]}

errno为0是成功上传完到后端后给前台的提示,都需要返回给前端页面。

这个弄清楚上传的流程就好了,代码这块自己发挥下就行。
我的博客文章地址:http://www.hanyz.cn/2017/06/29/%E4%BB%8B%E7%BB%8D%E4%B8%A4%E7%A7%8D%E5%AF%8C%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%99%A8/

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,914评论 25 707
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,789评论 6 342
  • 我从沼泽中挣脱,你却在岸上冷眼观望 所以起初我把你当希望信仰,但后来 我知道了,我做什么都是徒劳无功的 你从未愿意...
    DIVErGENt_B阅读 171评论 0 0
  • 1 .静态库所在的文件夹show in finder 2.打开终端 cd 拖入文件夹路径 3.lipo -info...
    你美你媚儿阅读 760评论 0 0