(Struts2+ajax+json)上传图片(文件)+ajaxfileupload.js插件的粗略分析

花时间买教训:
  调试代码过程中,要敢于直面问题的本质,不要舍本逐末,急于搜集一大堆资料,而不仔细研究问题本质,浪费更多的时间,不值得。
先说说应用场景:
  如题,前端页面利用ajax异步上传图片到服务器,交给Struts的action处理,返回json数据。
下面谈一谈踩到的一些坑,由于这个场景的例子网上已经很多,这里就不再重复造轮子,只是谈谈遇到的在这些例子中没有说到的问题
1. 为什么用ajaxfileupload?
  因为我前端要采用ajax异步的方式上传图片到服务器,而我不想通过表单提交的方式,不想多一个提交按钮,希望通过input标签的onchange()方法来触发ajax。如果采用一般的ajax传数据方式,服务器端不能接收这个图片,对于一般的string类型的参数可以接收,只要定义和前端相同名字的成员变量,并提供get和set方法就可以接收了。
2. 关于ajaxfileupload.js中的status这个变量的问题?
  它不是我们期望的那个ajax请求服务器后返回的status,插件ajaxfileupload.js中的仅仅通过一句status = isTimeout != “timeout” ? “success” : “error”;也就是请求超没超时来给status赋值,我觉得它并不是我action那边return的那个success或error,所以导致我ajax一直误以为接收到的status就是后台action return的直,这是一个大坑啊。后来我通过获取后台返回的数据来给status赋值,就解决了这个问题。修改部分代码如下:

requestDone = true;
var status;

//自己修改添加部分
var message = xml.responseText; //服务器返回的message内容(有些人用的result).由于struts配置返回类型是json,所以message返回的是jsonstring类型,这里判断要小心
if(  message == JSON.stringify("0") ){//服务器端返回status是error
    status = "error"
    jQuery.handleError(s, xml, status);
}else{
        try {
                status = isTimeout != "timeout" ? "success" : "error";
                // Make sure that the request was successful or notmodified
                if ( status != "error" )
                {
                    // process the data (runs the xml through httpData regardless of callback)
                    var data = jQuery.uploadHttpData( xml, s.dataType );
                    // If a local callback was specified, fire it and pass it the data
                    if ( s.success )
                          s.success( data, status );
                            // Fire the global callback
                            if( s.global )
                                jQuery.event.trigger( "ajaxSuccess", [xml, s] );
                        } else
                            jQuery.handleError(s, xml, status);
                    } catch(e)
                    {
                        status = "error";
                        jQuery.handleError(s, xml, status, e);
                    }

3. json对象,json字符串,普通字符串的区别?
  由于我的struts.xml配置返回json类型,后台execute()方法返回String类型,这就导致callback回调函数里获取的message其实是json字符串类型,注意这与普通字符串不一样,但如果你用typeof()来检验,结果也是string类型,这也是一个坑,如上面代码注释中所讲,所以才有了if判断里的JSON.stringify(“0”),将普通字符串”0”转化为json字符串,才能比较。至于json对象,想要ajax最后通过data.**的方式获取返回数据,就得先把普通字符串转化为json字符串var d = eval(“(“+data+”)”);//将数据转换成json类型,然后通过var j = JSON.parse(data); //把json字符串转化为json对象,才能用j.name取值,转化为json对象后就能方便的取值。

<struts>
    <package name="test" extends="json-default">
        <action name="uploadimg" class="Tools.Controller.UploadImgAction" method="execute">
            <result type="json" name="success">
                <param name="contentType">
                    text/html
                param>
                <param name="root">messageparam>
            result>
            <result type="json" name="error">
                <param name="contentType">
                    text/html
                param>
                <param name="root">messageparam>
            result>
        action>
    package>
struts>
                //将数据存储在map里,再转换成json类型数据,也可以自己手动构造json类型数据
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("name", "tao");
                map.put("id", "123");
                JSONObject json = JSONObject.fromObject(map);//将map对象转换成json类型数据
                message = json.toString();//给result赋值,传递给页面
                is.close();
                os.flush();
                System.out.println(message);
                return SUCCESS;
            }
        } catch (Exception e) {
            e.printStackTrace();
            message = "0";
        }
        message = "0";
        System.out.println(message);
        return ERROR;
        $.ajaxFileUpload
        (
            {
                url:'uploadimg.action',//用于文件上传的服务器端请求地址
                secureuri:false,//一般设置为false
                fileElementId:'imgfile',//文件上传空间的id属性  
                dataType:'json',//返回值类型 一般设置为json
                success: function (data, status)  //服务器成功响应处理函数
                {
//                    var d = eval("("+data+")");//将数据转换成json类型,可以把data用alert()输出出来看看到底是什么样的结构
                    alert("status:"+status);
                    alert(data);
                    alert("data type is: "+typeof (data));
//                    var d = eval("("+data+")");   //把普通字符串转化为json 字符串
//                    var j = JSON.parse( data );   
//                    alert(j);
//                    alert(typeof(j));
//                    alert("j.name:"+j.name);
//                    alert(d);
//                    alert("d type is: "+typeof (d));
                    var j = JSON.parse(data);   //把json字符串转化为json对象,才能用j.name取值
                    alert("j type is: "+typeof (j));
                    alert("j : "+typeof (j));
                    alert("j.name:"+j.name);
//                    alert(d.user.name);
//                    alert(d.success);//从服务器返回的json中取出message中的数据,其中message为在struts2中action中定义的成员变量
                    $("#log_window").css('display','block');
                    $('.main').css('display','none');
                    $('body').css('background-color','#666')
                },
                error: function (data, status, e)//服务器响应失败处理函数
                {
                    alert("识别失败!请尝试重新上传。。。");
                    window.location.reload();
                }
            }
        )

4. 最后说说ajaxfileupload.js中方法uploadHttpData的问题?
  这里我遇到网上有人说的dataType参数要大写的问题,我用大写的JSON就能成功返回数据,用小写老是返回error,后来调试到这里发现原来是var am = rx.exec(data);这句话的问题,这部分代码如下。直接看json条件里面,代码通过一个正则表达式,要去除pre标签,问题就出在var am = rx.exec(data);这句话执行之后am的值为null,后面通过am来给data赋值当然为空,可能是我这里返回的data就没有他说的pre标签,我一直用的chrome浏览器测试,或许其他浏览器会出现,所以我加了个判断,没有就直接返回data,然后就能正常返回数据了。

uploadHttpData: function( r, type ) {
        var data = !type;
        data = type == "xml" || data ? r.responseXML : r.responseText;
        // If the type is "script", eval it in global context
        if ( type == "script" )
            jQuery.globalEval( data );
        // Get the JavaScript object, if JSON is used.
        if ( type == "json" )
        {
            // If you add mimetype in your response,
            // you have to delete the '
' tag.
// The pre tag in Chrome has attribute, so have to use regex to remove var data = r.responseText; var rx = new RegExp("(.*?)
","i"); var am = rx.exec(data); if( am != null ){ //this is the desired data extracted var data = (am) ? am[1] : ""; //the only submatch or empty } eval( "data = " + data ); //将数据转换成json类型 } // evaluate scripts within html if ( type == "html" ) jQuery("
").html(data).evalScripts(); //alert($('param', data).each(function(){alert($(this).attr('value'));})); return data; }

你可能感兴趣的:(j2ee(javaWeb))