Ueditor之图片上传功能如何和真实项目结合使用

开心一笑

周末,五六个朋友聚餐,席间,阿凌注意到阿艳沉默少语,不比以往的活波开朗,像有心事。饭后回去的路上,阿凌走到阿艳身边说:“你的电量好像不够了?”
阿艳:“啊,什么?”
阿凌:“看你好像关掉了好多程序,今天不见你说话,也不见你笑。”这时,阿凌指着阿艳的脸接着说道:“看,就只剩屏幕还安静地亮着。”
阿艳再也忍不住,开心地笑了,本来不打算说,就这样一个人忧伤的,但现在这样一笑,顿时觉得也没什么大不了,于是就和阿凌说了她的心事。她的闺蜜和她相处三年的男朋友分手了,原本看他们那么幸福甜蜜,就像天生注定的一样,没想到也这样分了,让她对感情又多了一分失望。
听完后,阿凌说到:“你知道吗?有一种人和TA们恋爱,肯定不会分手。”
阿艳:“是吗?哪一种?”
阿凌:“有一种人,他们只有脚。”
阿艳:“啊哈哈,你好坏……”

提出问题

Ueditor图片上传功能如何和真实项目结合使用呢???

解决问题

  • 假如你已经看了我的前一篇文章《UEditor之基于Java图片上传前后端源码研究》,这一点很重要的啊,当然不看也可以,因为你已经是一个高手,哈哈;
  • 假如你已经看了我的第二篇关于ueditor的文章;
  • 假如你已经安装tomcat服务器;
  • 假如你已经把项目运行到Eclipse上;
  • 假如你已经有java基础;
  • 假如你对js有一定基础;
  • 假如你已经下载ueditor1_4_3_3-src源码,记得是开发的哦;

其实前两章只是简单介绍Ueditor如何使用,接下来才是重头戏

在真实项目中,我们通常已经有自己的图片上传接口了,可是我们在前两章中,知道,ueditor后端的代码并不支持,好蛋碎啊!!!!!

所有才写这篇文章,让别人少走弯路吧!!!!!

开始吧!!!

1.首先,我们定义一个名为GetConfigServlet的Servlet,真实项目应该是一个Controller,一样的,这个类就是加载后端配置文件类

package com.ay.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.baidu.ueditor.ActionEnter;

/**
 * 该类主要是获取配置文件
 * @author Ay
 * Servlet implementation class GetConfigServlet
 */
@WebServlet("/GetConfigServlet")
public class GetConfigServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public GetConfigServlet() {
        super();
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //这里就是把controller.jsp代码copy下来
        request.setCharacterEncoding( "utf-8" );
        response.setHeader("Content-Type" , "text/html");
        String roolPath = request.getSession().getServletContext().getRealPath("/");
        //记得把config.json放到/Test/WEB-INF/下
        String configStr = new ActionEnter(request, roolPath).exec();
        System.out.println(realPath);
        response.getWriter().write(configStr);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        
    }

}

下面是我的代码分布图片:

这里写图片描述

2.修改ueditor.config,把serverUrl的路径改为我们自己写的后端接口路径,也就是GetConfigServlet类

//原来    
// 服务器统一请求接口路径
, serverUrl: URL + "jsp/controller.jsp"

//改为
, serverUrl: URL + "GetConfigServlet"

3.上面就可以加载出富文本框了,这里介绍一个js类loadconfig.js:

    (function(){

    UE.Editor.prototype.loadServerConfig = function(){
        var me = this;
        setTimeout(function(){
            try{
                me.options.imageUrl && me.setOpt('serverUrl', me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2'));

                var configUrl = me.getActionUrl('config'),
                    isJsonp = utils.isCrossDomainUrl(configUrl);

                /* 发出ajax请求 */
                me._serverConfigLoaded = false;

                configUrl && UE.ajax.request(configUrl,{
                    'method': 'GET',
                    'dataType': isJsonp ? 'jsonp':'',
                    'onsuccess':function(r){
                        try {
                            var config = isJsonp ? r:eval("("+r.responseText+")");
                            utils.extend(me.options, config);
                            me.fireEvent('serverConfigLoaded');
                            me._serverConfigLoaded = true;
                        } catch (e) {
                            showErrorMsg(me.getLang('loadconfigFormatError'));
                        }
                    },
                    'onerror':function(){
                        showErrorMsg(me.getLang('loadconfigHttpError'));
                    }
                });
            } catch(e){
                showErrorMsg(me.getLang('loadconfigError'));
            }
        });

        function showErrorMsg(msg) {
            console && console.error(msg);
            //me.fireEvent('showMessage', {
            //    'title': msg,
            //    'type': 'error'
            //});
        }
    };

    UE.Editor.prototype.isServerConfigLoaded = function(){
        var me = this;
        return me._serverConfigLoaded || false;
    };

    UE.Editor.prototype.afterConfigReady = function(handler){
        if (!handler || !utils.isFunction(handler)) return;
        var me = this;
        var readyHandler = function(){
            handler.apply(me, arguments);
            me.removeListener('serverConfigLoaded', readyHandler);
        };

        if (me.isServerConfigLoaded()) {
            handler.call(me, 'serverConfigLoaded');
        } else {
            me.addListener('serverConfigLoaded', readyHandler);
        }
    };

})();

4.可是有没有发现一个问题,调用服务端的统一接口已经被加载配置文件给占用了,接下来上传文件接口没有了,怎么办呢,怎么办呢,怎么办呢???

其实UEditor官网在第五章已经讲了,看第五章的:

如何自定义请求地址
本文档说明修改请求地址的方法。

应用场景
ueditor 1.4.2+ 推荐使用唯一的请求地址,通过GET参数action指定不同请求类型。
但很多用户都希望使用自己写好的上传地址,
下面提供一种解决方法: 由于所有ueditor请求都通过editor对象的getActionUrl方法获取请求地址,可以直接通过复写这个方法实现,例子如下:

UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl;
UE.Editor.prototype.getActionUrl = function(action) {
    if (action == 'uploadimage' || action == 'uploadscrawl' || action == 'uploadimage') {
        return 'http://a.b.com/upload.php';
    } else if (action == 'uploadvideo') {
        return 'http://a.b.com/video.php';
    } else {
        return this._bkGetActionUrl.call(this, action);
    }
}

上面是官方文档,只要覆盖掉原型中的getActionUrl即可

5.我们首先再创建一个类:fileUploadServlet.java,用于处理文件上传的代码

package com.ay.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class fileUploadServlet
 */
@WebServlet("/fileUploadServlet")
public class fileUploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public fileUploadServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
    }

}

其次修改config.jso配置文件,把imageActionName的值改为上传文件的路径,如下:

 /* 上传图片配置项 */
"imageActionName": "fileUploadServlet", /* 执行上传图片的        action名称 */

最后,我们在simpleupload.html上添加如下代码:

<!DOCTYPE HTML>
<html>
<head>

    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title></title>
    <script type="text/javascript" charset="utf-8" src="../ueditor.config.js"></script>
    <script type="text/javascript" charset="utf-8" src="editor_api.js"></script>
</head>
<body>
    <h1>UEditor简单功能</h1>

    <!--style给定宽度可以影响编辑器的最终宽度-->
    <script type="text/plain" id="myEditor">
        <p>这里我可以写一些输入提示</p>
    </script>
    <script type="text/javascript">
        UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl;
        
        UE.getEditor('myEditor',{
            //这里可以选择自己需要的工具按钮名称,此处仅选择如下五个
            //toolbars:[['FullScreen','simpleupload','Source', 'Undo', 'Redo','Bold','test']],
            //focus时自动清空初始化时的内容
            autoClearinitialContent:true,
            //关闭字数统计
            wordCount:false,
            //关闭elementPath
            elementPathEnabled:false,
            //默认的编辑区域高度
            initialFrameHeight:300
            //更多其他参数,请参考ueditor.config.js中的配置项
        });
        UE.Editor.prototype.getActionUrl = function(action) {
                //这里很重要,很重要,很重要,要和配置中的imageActionName值一样
                if (action == 'fileUploadServlet') {
                //这里调用后端我们写的图片上传接口
                return 'http://localhost:8081/Test/fileUploadServlet';
            }else{
                 return this._bkGetActionUrl.call(this, action);
            }
        }
        
        
    </script>

</body>


</html>

图片上传的类:

package com.ay.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class fileUploadServlet
 */
@WebServlet("/fileUploadServlet")
public class fileUploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public fileUploadServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        //这里就是我们项目中真实的代码了
        //文件上传肯定是post请求
        System.out.println("--------图片上传成功---------------");
        System.out.println("------------------------------");
        System.out.println("--------图片上传成功-----------");
    }

}

写到这里基本就完了,可是你有没有发现,有个问题

一般情况下,我们项目的上传接口以及写好了,且返回到前端的json数据也定了,可是Ueditor需要的json格式和我们项目中返回的json数据不一样,怎么办呢?

一般情况下,我们项目的上传接口以及写好了,且返回到前端的json数据也定了,可是Ueditor需要的json格式和我们项目中返回的json数据不一样,怎么办呢?

一般情况下,我们项目的上传接口以及写好了,且返回到前端的json数据也定了,可是Ueditor需要的json格式和我们项目中返回的json数据不一样,怎么办呢?

看下面:

首先,我们看看Ueditor图片上传成功后,返回的json数据

{
"state": "SUCCESS",
"original": "80px - \u526f\u672c (2).jpg",
"size": "13252",
"title": "1465731377326075274.jpg",
"type": ".jpg",
"url": "/ueditor/jsp/upload/image/20160612/1465731377326075274.jpg"
}

也就是说,如果我们调用自己的图片上传接口,返回的json数据改造成Ueditor需要的json数据即可,在哪里改呢

在simpleupload.js的callback中

function callback(){
                try{
                    var link, json, loader,
                        body = (iframe.contentDocument || iframe.contentWindow.document).body,
                        result = body.innerText || body.textContent || '';
                    
                    //这里result就是我们真实项目返回的json数据
                    //很简单写个方法,把老的json变成Ueditor需要的json
                    oldJson = (new Function("return " + result))();
                    //这个方法是我写的,用来转化
                    var json =  changeDataToJson(json);
                    link = me.options.imageUrlPrefix + json.url;
                    if(json.state == 'SUCCESS' && json.url) {
                        loader = me.document.getElementById(loadingId);
                        loader.setAttribute('src', link);
                        loader.setAttribute('_src', link);
                        loader.setAttribute('title', json.title || '');
                        loader.setAttribute('alt', json.original || '');
                        loader.removeAttribute('id');
                        domUtils.removeClasses(loader, 'loadingclass');
                    } else {
                        showErrorLoader && showErrorLoader(json.state);
                    }
                }catch(er){
                    showErrorLoader && showErrorLoader(me.getLang('simpleupload.loadError'));
                }
                form.reset();
                domUtils.un(iframe, 'load', callback);
            }
            /** 自己写的方法,你们可以自己去实现 **/
            function changeDataToJson(json){
                var object = {"original":'',"size":'',
                        "state":'',"title":'',"type":'',
                        "url":''};
                
                var _json = json;
                //。。。。。自己真实项目的逻辑
                //。。。。。自己真实项目的逻辑
                return object;
            }

其实,写到这里基本就结束了,可是还有一个问题

就是,一般,我们图片上传,会把图片上传到服务器的某个盘里,比如:C盘 或者D盘,不太会把它放到项目部署目录下,因为一旦项目重新部署,图片就会消失

这就引发一个问题,先看下面能成功的上传和显示的图片,注意到图片是放到 项目的/ueditor/jsp/upload ... 目录下,所以没问题

<img src="http://localhost:8081/Test//ueditor/jsp/upload/image/20160612/1465731377326075274.jpg" 
title="1465731377326075274.jpg" 
_src="http://localhost:8081/Test//ueditor/jsp/upload/image/20160612/1465731377326075274.jpg" 
alt="80px - 副本 (2).jpg">
这里写图片描述

可是,我们真实项目是放到非tomcat目录下,如C,D盘,这时候,是这样的:

<img src="D:/upload/image/20160612/1465731377326075274.jpg" 
title="1465731377326075274.jpg" 
_src="http://localhost:8081/Test//ueditor/jsp/upload/image/20160612/1465731377326075274.jpg" 
alt="80px - 副本 (2).jpg">

如果是这样的或,google浏览器会报:

这里写图片描述

解决方法是:

该方法是我们真实项目的一个controller层,提供一个方法,获得图片流

/**
 * 根据ID获取图片流
 *
 * @param id
 * @param request
 * @param response
 * @throws IOException
 */
@RequestMapping(value = "/{id}/image", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public void image(@PathVariable("id") String id,
        HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    SysAttachment sysAttachment = sysAttachmentService.findById(id);
    AssertUtils.checkResourceFound(sysAttachment);
    response.setContentType("image/x-png");
    response.setCharacterEncoding("UTF-8");
    File file = new File(sysAttachment.getPath());
    BufferedImage image = ImageIO.read(file);
    ImageIO.write(image, sysAttachment.getType(), response.getOutputStream());
}

也就是说,继续通过调用后端的接口,获得图片

这时候,img便签变成,下面的 "xxx/xxx/image" 就是真实项目的controller的映射路径了

<img src="xxx/xxx/image" title="1465731377326075274.jpg" 
_src="http://localhost:8081/Test//ueditor/jsp/upload/image/20160612/1465731377326075274.jpg" 
alt="80px - 副本 (2).jpg">

好了,真的结束了.....

最后用一张图片,表达下上面的逻辑:

这里写图片描述

读书感悟

来自《悬崖上的金鱼姬》

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,518评论 25 707
  • 开心一笑 下班后,阿华到楼下小超市买毛巾,刚买完出来,就遇到同一办公楼里另一家公司的阿菲,之前与她远远的有过几次眼...
    阿_毅阅读 14,034评论 4 7
  • 大海又催稿了,催钟悦写故事。大海何许人也?钟悦的高中同学。说来也怪,上学的时候,对他的记忆可谓是空白,...
    一心清静阅读 1,302评论 0 2
  • 一直以来,每当遇到一些不太顺利的事情,或者感觉自己说错话、做错事的时候,我都会告诉自己,所有事情最后都会有好的结果...
    处处1阅读 4,433评论 0 2
  • 补习班有个孩子,一年级。8个月大的时,母亲离家,去年的这个时候父亲因白血病离开。 我说,如果考试考好了,我...
    大太阳爱谁阅读 282评论 0 0