做了一個檔案上傳模組,因為傳統的form提交會有頁面重新整理,不符合我的使用要求,所以我採用Ajax提交方式,這裡說明下,我的應用程式前端為Ajax提交,後端SpringMVC接收處理。
傳統form提交檔案方式:
<form id="uploadPic" action="/user/saveHeaderPic" method="post" enctype="multipart/form-data"> <input type="file" name="file"/> <input type="submit" value="提交"/></form>
採用Ajax提交檔案,我先後出現了如下兩個問題:
Ajax post 400 (Bad Request)
HTTP Status 400 - Required CommonsMultipartFile parameter ‘pic’ is not present
這裡先解釋下錯誤原因:
問題1:
Ajax參數錯誤導致,上傳檔案的form我使用了jquery.form.js的form序列化,這樣傳輸表單到後台很方便,但是二進位檔案是無法用form.serialize()序列化的。
所以最終我採用了FormData的傳輸方式,XMLHttpRequest Level 2添加了一個新的介面FormData。利用FormData對象,我們可以通過JavaScript用一些索引值對來類比一系列表單控制項,我們還可以使用XMLHttpRequest的send()方法來非同步提交這個“表單”。比起普通的ajax,使用FormData的最大優點就是我們可以非同步上傳一個二進位檔案。
但使用formData對瀏覽器有一定要求(Chrome 7+、Firefox 4+、IE 10+、Opera 12+、Safari 5+),如果程式需要相容低版本瀏覽器,可去查看其他JS上傳控制項或flash上傳控制項。
formData使用參看:https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/FormData
問題2:
這個問題是因為不細心導致的 - -,後端接收的參數名和前端file控制項name名稱不一致導致。
好啦,下面給出我的前後端程式碼範例:
HTML:
<form id="uploadPic" action="#" enctype="multipart/form-data"> <input type="file" name="file"> <a href="javascript:savePic();" class="btn green"> 提交 </a></form>
JS指令碼:
<script type="text/javascript"> function savePic(){ var formData = new FormData($( "#uploadPic" )[0]); var ajaxUrl = "${path}/rest/user/saveHeaderPic"; //alert(ajaxUrl); //$('#uploadPic').serialize() 無法序列化二進位檔案,這裡採用formData上傳 //需要瀏覽器支援:Chrome 7+、Firefox 4+、IE 10+、Opera 12+、Safari 5+。 $.ajax({ type: "POST", //dataType: "text", url: ajaxUrl, data: formData, async: false, cache: false, contentType: false, processData: false, success: function (data) { alert(data); }, error: function(data) { alert("error:"+data.responseText); } }); return false; }
JAVA後端:
/** * 頭像圖片上傳 * @throws IOException */@RequestMapping(value = "/saveHeaderPic", method = RequestMethod.POST)public void saveHeaderPic(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request, HttpServletResponse response) throws IOException { String resMsg = ""; try { long startTime=System.currentTimeMillis(); System.out.println("fileName:"+file.getOriginalFilename()); String path="/Users/loukai/easylife/files/"+new Date().getTime()+file.getOriginalFilename(); System.out.println("path:" + path); File newFile=new File(path); //通過CommonsMultipartFile的方法直接寫檔案 file.transferTo(newFile); long endTime=System.currentTimeMillis(); System.out.println("已耗用時間:"+String.valueOf(endTime-startTime)+"ms"); resMsg = "1"; } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); resMsg = "0"; } response.getWriter().write(resMsg); }
運行測試,檔案上傳成功。