解決使用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版本下載(見附件):