解决使用ajaxFileUpload上传控件出现的问题:回调函数总是进入error或success
上周说到做excel的导入时,用到了jquery的一个上传控件ajaxFileUpload,但今天测试的时候,却出现了问题:
我们不妨先来查看一下ajaxFileUpload的基本语法:
$.ajaxFileUpload ({ url:xxx, secureuri:false, //上传处理地址 fileElementId:'fileToUpload', //上传文件的id dataType: 'json', //传输的数据类型,默认为text //成功响应后回调的函数 data为后台返回的数据 status为成功或失败状态 success: function (data, status) { //some code }, //响应失败后回调的函数 e为错误信息 error: function (data, status, e) { //some code } } )
结果我发现,是无论后台响应是否成功,它都是进入回调函数error:
而我本地写的上传的js如下:
$.ajaxFileUpload({ url : "demo/import.json", //dataType : 'json', secureuri : false, fileElementId : 'file', success : function(res, status) { //some code }, error : function(data, status, e) { //some code } } );
后来发现,我竟然把dataType注掉了。。,并且无论后台是否响应成功,都进的是error回调……因此我把dataType指定为json,
而检查我的后台,发现
我用的google浏览器,debug才发现demo/import.json所对应的后台代码:
@RequestMapping("/demo/import.json") @ResponseBody public String import(@RequestParam(value = "excelFile") MultipartFile excelFile, HttpServletRequest request) { String fileName = excelFile.getOriginalFilename(); String result = ""; try{ //some code result = "success"; } catch(Exception e) { e.printStackTrace(); result = "fail"; } return result; }
返回的是String,该String并不是json格式的。改之:
@RequestMapping("/demo/import.json") @ResponseBody public String import(@RequestParam(value = "excelFile") MultipartFile excelFile, HttpServletRequest request) { String fileName = excelFile.getOriginalFilename(); String result = ""; Map map = new HashMap(); String jsonStr = null; try{ //some code result = "success"; } catch(Exception e) { e.printStackTrace(); result = "fail"; } map.put("data", result); jsonStr = String.valueOf(JSONObject.fromObject(map)); return jsonStr; }
而之前前台没指定dataType,因为传输的数据类型对应不上,所以无论成功与否都会进入error。
同样模拟测试后台响应成功和响应失败,问题依然出现。。
看到网上说的,可能是ajaxfileupload.js版本的问题,即里面判断返回数据类型的js函数:
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" ) eval("data = "+data); // evaluate scripts within html if ( type == "html" ) jQuery("<div>").html(data).evalScripts(); //alert($('param', data).each(function(){alert($(this).attr('value'));})); return data; }
这个js函数表明,当type为json时,直接把回调函数参数里的data指定为后台给你返回的data,但通过google浏览器debug这个方法才发现即使后台返回值类型改成json格式的String,并指定前台dataType属性为json时,获取到的data为<pre style="word-wrap: break-word; white-space: pre-wrap;">{"data":"success"}</pre>他并不是从后台获取到纯json格式的字符串,改正:
if ( type == "json" ) eval("data = "+$(data).html());
清除浏览器缓存,重测,即可得到中间的json 串{"data":"success"}。
这样,无论后台响应成功与否,它不会只进入error了。
但现在问题又来了,虽然不会只进入error但是问题又来了。。无论是否响应成功,它又只进入success回调了,感觉很无语。
同样,通过debug,发现前台回调时,即使后台响应失败,也会给前台返回一个json {”data:“ "fail"},只要有json,他就会进入success。虽说我可以通过在success里取data对应的值,根据data对应的值是success还是fail判断到底是成功响应还是失败响应,但终归不太合理。仔细检查后台代码后,改之:
@RequestMapping("/demo/import.json") @ResponseBody public String import(@RequestParam(value = "excelFile") MultipartFile excelFile, HttpServletRequest request) { Map map = new HashMap(); String jsonStr = null; try{ //some code result = "success"; map.put("data", result); jsonStr = String.valueOf(JSONObject.fromObject(map)); //只有响应成功才会得到json格式的字符串——前台进入success回调 } catch(Exception e) { e.printStackTrace(); result = "fail"; //map.put("data", result); //如果响应失败,则不会生成json格式的字符串,返回的就只是一个空的String而已——前台进入error回调 } return jsonStr; }
再次模拟成功和失败响应之后,终于”各找各妈“了——成功响应的进入success回调,响应失败的进入error回调。。
小结:如果是传输类型是json格式,如果后台返回的不是json格式的字符串,则前台只会进error回调;如果后台返回的是json格式的字符串,但如果响应失败也给他返回一个json字符串时,前台也会进入success回调。
推荐一个相对稳定的ajaxFileUpload.js版本下载(见附件):
相关推荐
为了美观,把 type="file" 控件隐藏。点击“上传”按钮,click调用隐藏文件控件,再选择文件。查了一遍,好像是ie为了安全控制,文件的必须鼠标点击过后,才能提交。还没有想到其他的方法。。。
5,success 提交成功后自动执行的处理函数,参数data就是服务器返回的数据。6,error 提交失败自动执行的处理函数。7,data 自定义参数。fileElementId: 'file1',