1、多檔案上傳:http://blog.csdn.net/a1314517love/article/details/24183273
2、單檔案上傳的簡單示例:http://blog.csdn.net/cheung1021/article/details/7084673
3、springMVC+ajaxfileupload非同步上傳圖片並及時預覽
http://www.codeweblog.com/springmvc-ajaxfileupload%E5%BC%82%E6%AD%A5%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87%E9%A2%84%E8%A7%88-%E8%A3%81%E5%89%AA%E5%B9%B6%E4%BF%9D%E5%AD%98%E5%9B%BE%E7%89%87/
個人實踐:
一、對1中的第二種方法的實現:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>${pageTitle }</title> <link href="/Public/media/css/new/page.css" rel="stylesheet" type="text/css" /> </head> <body> <form action="${pageContext.request.contextPath}/workConfig/upload" method="post" enctype="multipart/form-data"> name:<input name="name" type="text" ><br /> <input name="file" type="file" ><br /> <input name="file2" type="file" ><br /> <input name="file3" type="file" ><br /> <input name="file4" type="file" ><br /> <input type="submit" value="提交"> </form> </body> </html>
package com.leslie.controller; import java.io.File; import java.io.IOException; import java.util.Iterator; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.ModelAndView; import com.leslie.User; @Controller @RequestMapping("/workConfig") public class SJWorkConfigController { private Logger log = LoggerFactory.getLogger(SJWorkConfigController .class); @RequestMapping(value = "/upload") public ModelAndView upload(@Valid @ModelAttribute User user, BindingResult br, HttpServletRequest request, HttpServletResponse response) throws IllegalStateException, IOException { // 建立一個通用的多部分解析器 CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver( request.getSession().getServletContext()); // 判斷 request 是否有檔案上傳,即多部分請求 if (multipartResolver.isMultipart(request)) { // 轉換成多部分request MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; // 取得request中的所有檔名 Iterator<String> iter = multiRequest.getFileNames(); while (iter.hasNext()) { // 記錄上傳過程起始時的時間,用來計算上傳時間 // int pre = (int) System.currentTimeMillis(); // 取得上傳檔案 MultipartFile file = multiRequest.getFile(iter.next()); if (file != null) { // 取得當前上傳檔案的檔名稱 String myFileName = file.getOriginalFilename(); // 如果名稱不為“”,說明該檔案存在,否則說明該檔案不存在 if (myFileName.trim() != "") { System.out.println(myFileName); // 重新命名上傳後的檔名 String fileName = "demoUpload" + file.getOriginalFilename(); // 定義上傳路徑 String path = "E:/test/" + fileName; File localFile = new File(path); file.transferTo(localFile); } } // 記錄上傳該檔案後的時間 // int finaltime = (int) System.currentTimeMillis(); // System.out.println(finaltime - pre); } } ModelAndView mv = new ModelAndView(); mv.addObject("message", request.getParameter("name").toString()); mv.setViewName("hello"); return mv; } // @RequestMapping(value = "/upload") // public ModelAndView upload(DefaultMultipartHttpServletRequest request) { // CommonsMultipartFile file = (CommonsMultipartFile) // request.getFile("file"); // // 這裡的file就是前臺頁面的name // if (file.isEmpty()) { // return null; // } // // 獲取路徑,生成完整的檔案路徑 // String fileName = "E:/test/"+"demoUpload" + file.getOriginalFilename(); // File uploadFile = new File(fileName); // try { // // 上傳 // FileCopyUtils.copy(file.getBytes(), uploadFile); // } catch (IOException e) { // e.printStackTrace(); // } // ModelAndView mv = new ModelAndView(); // mv.addObject("message",request.getParameter("name").toString()); // mv.setViewName("hello"); // return mv; // } }
1、1中的方法比較通用,且一次能上傳多個檔案。
2、雖然request的型別是MultipartHttpServletRequest,但仍可繼續使用request.getParameter來正常取表單中的非Multipart內容,
這樣就可以將圖片和普通表單內容一次提交了。
二、對3中方法的實現
注:3文中不但實現了圖片上傳和預覽,並且有使用js切圖的功能。由於我使用java在後臺切圖,所以只使用了它的檔案上傳預覽功能。
前臺頁面程式碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>${pageTitle }</title> <link href="/Public/media/css/new/page.css" rel="stylesheet" type="text/css" /> <style type="text/css"> .errormsg { font-family: "微軟雅黑"; color: #F30; } </style> </head> <body> <div class="outer"> <div class="pathdiv"> ${currentMenuDesc } <div class="tableDivTitleButtonDiv"> <a href="${backToURL}"><input type="button" class="tableDivTitleButtonDivButton" value="返回" /></a> </div> </div> <div class="infoTitle">${pageTitle }</div> <form:form action="${formActionURL}" method="post" commandName="work"> <div class="formDiv"> <table width="1020" border="0"> <tr> <form:input path="worksId" type="hidden" /> <form:input path="designerId" type="hidden" /> <form:input path="worksImg1" type="hidden" /> <form:input path="worksImg2" type="hidden" /> <form:input path="worksImg3" type="hidden" /> <td align="right">作品名稱:</td> <td align="left"><form:input path="worksName" /><span class="errormsg"><form:errors path="worksName" /></span></td> </tr> <tr> <td align="right">作品說明:</td> <td align="left"><form:textarea path="worksRemark" cols="30" rows="10" /><span class="errormsg"><form:errors path="worksRemark" /></span></td> </tr> <tr> <td align="right">作品圖1:</td> <td align="left"> <input name="realPicFile" id="realPicFile" type="file" onchange="ajaxFileUpload()"/> <img src="/Public/media/image/loading2.gif" id="loading" style="display: none;"> <img id="realPic" src="/Public/showimgbj.jpg"/> <span class="errormsg"> <form:errors path="worksImg1" /> </span> </td> </tr> <tr> <td align="right">作品圖2:</td> <td align="left"><input name="" type="file" /><img id="img2" src="" /><span class="errormsg"><form:errors path="worksImg2" /></span></td> </tr> <tr> <td align="right">作品圖3:</td> <td align="left"><input name="" type="file" /><img id="img3" src="" /><span class="errormsg"><form:errors path="worksImg3" /></span></td> </tr> <tr> <td></td> <td><input name="" type="submit" value="提交" /></td> </tr> </table> </div> </form:form> </div> <div id="errorMsgDiv"></div> <script src="/Public/media/js/jquery-1.10.1.min.js" type="text/javascript"></script> <script src="/Public/media/js/jquery-migrate-1.2.1.min.js" type="text/javascript"></script> <script src="/Public/media/js/bootstrap.min.js" type="text/javascript"></script> <script src="/Public/media/js/jquery.gritter.js" type="text/javascript"></script> <script src="/Public/media/js/app.js" type="text/javascript"></script> <script src="/Public/media/css/new/ajaxfileupload.js" type="text/javascript"></script> <script> jQuery(document).ready(function() { App.init(); // initlayout and core plugins }); </script> <script> function ajaxFileUpload() { var file = $("#realPicFile").val(); if(!/\.(gif|jpg|jpeg|png|JPG|PNG)$/.test(file)){ Error("不支援的圖片格式.圖片型別必須是.jpeg,jpg,png,gif格式."); return false; } $.ajaxFileUpload({ url : '${pageContext.request.contextPath}/workConfig/uploadOnePic?inputId=realPicFile', secureuri : false, fileElementId : 'realPicFile', dataType : 'content', success : function(data, status){ $("#realPic").attr("src", data); }, error : function(data, status, e){ alert(e); //Error(e); } }); return false; } </script> </body> </html>
後臺controller程式碼(不包括切圖):
package com.leslie.controller; import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.ModelAndView; import com.leslie.model.DesignerWorks; import com.leslie.model.MemberDesigner; import com.leslie.model.User; import com.leslie.service.DesignerService; import com.leslie.util.ConstantsUtil; import com.leslie.validator.DesignerWorksValidator; @Controller @RequestMapping("/workConfig") public class SJWorkConfigController { @RequestMapping("/uploadOnePic") @ResponseBody public String fileUpload(String inputId, MultipartHttpServletRequest request) { try { MultipartFile realPicFile = request.getFile(inputId); if (realPicFile != null) { // 取得當前上傳檔案的檔名稱 String myFileName = realPicFile.getOriginalFilename(); // 如果名稱不為“”,說明該檔案存在,否則說明該檔案不存在 if (myFileName.trim() != "") { System.out.println(myFileName); // 重新命名上傳後的檔名 String fileName = "demoUpload" + realPicFile.getOriginalFilename(); // 定義上傳路徑 String path = "D:/program files/apache-tomcat-8.0.33/webapps/Public/upload/images/" + fileName; String pathReturn = "/Public/upload/images/" + fileName; File localFile = new File(path); realPicFile.transferTo(localFile); return pathReturn; } } } catch (Exception e) { // LOG.error("upload header picture error : ", e); } return null; } }
過程概述:使用者點選了檔案選擇器的按鈕以後,瀏覽器彈出選擇檔案的對話方塊,當使用者選定了某張圖片並確定以後,會觸發檔案選擇器的onchange事件,我們在onchange事件裡呼叫ajaxfileupload將檔案選擇器
選中的檔案提交到後臺處理,後臺通過request拿到檔案以後,可以裁剪,可以儲存,可以做很多事情,然後將儲存以後的檔案的url路徑返回給前臺ajaxfileupload,ajaxfileupload拿到檔案路徑以後,將頁面中
相應的img標籤的src屬性改成檔案路徑,然後這張圖片就在頁面中顯示出來了。
說明:
1、ajaxfileupload的功能只是將檔案提交到後臺,真正對圖片進行儲存、裁切等處理的還是後臺程式。
2、ajaxfileupload的dataType屬性一般為"json",但我在使用json型別時報錯,後臺返回給前臺資料以後走到了error分支,彈出“syntexError:unexpeted token”。網上搜了一下,有高人通過修改
ajaxfileupload原始碼解決了問題(原文地址:http://liwx2000.iteye.com/blog/1540321),但我在實踐中按它的辦法修改問題依然存在,於是我將型別改為content就搞定了,正確返回了檔案的路徑
並走入了success分支。
3、在儲存檔案時定義了兩個檔案路徑,path指的是圖片在伺服器本地儲存的絕對路徑,pathReturn指的是使用者在瀏覽器上看到的圖片的src路徑,此處需要注意,如果將path直接返回,
頁面上是看不到圖片的。
4、ajaxfileupload.js的下載:http://www.cnblogs.com/kissdodog/archive/2012/12/15/2819025.html
三、後記
按照二中的辦法,似乎一切順風順水波瀾不驚,但卻有一個問題無法解決:雖然使用ajaxfileupload成功完成了圖片的上傳和及時預覽,但檔案選擇器(<input type="file")在選中了圖片以後卻始終無法顯示
圖片的url,一直顯示“未選擇檔案”,這似乎是ajaxfileupload的一個bug。最後我使用了一個折中的辦法,將檔案選擇器隱藏,使用一個普通的按鈕,當它被點選時觸發檔案選擇器的onclick事件。下面重新給出整理以後的程式碼。
jsp程式碼
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>${pageTitle }</title> <link href="/Public/media/css/new/page.css" rel="stylesheet" type="text/css" /> <style type="text/css"> .errormsg { font-family: "微軟雅黑"; color: #F30; } </style> </head> <body> <div class="outer"> <div class="pathdiv"> ${currentMenuDesc } <div class="tableDivTitleButtonDiv"> <a href="${backToURL}"><input type="button" class="tableDivTitleButtonDivButton" value="返回" /></a> </div> </div> <div class="infoTitle">${pageTitle }</div> <form:form action="${formActionURL}" method="post" commandName="work"> <div class="formDiv"> <table width="1020" border="0"> <tr> <form:input path="worksId" type="hidden" /> <form:input path="designerId" type="hidden" /> <form:input id = "hiddenImgValue1" path="worksImg1" type="hidden" /> <form:input id = "hiddenImgValue2" path="worksImg2" type="hidden" /> <form:input id = "hiddenImgValue3" path="worksImg3" type="hidden" /> <td align="right">作品名稱:</td> <td align="left"><form:input path="worksName" /><span class="errormsg"><form:errors path="worksName" /></span></td> </tr> <tr> <td align="right">作品說明:</td> <td align="left"><form:textarea path="worksRemark" cols="30" rows="10" /><span class="errormsg"><form:errors path="worksRemark" /></span></td> </tr> <tr> <td align="right">作品圖1:</td> <td align="left"> <img src="/Public/media/image/loading2.gif" id="loading" style="display: none;"> <img id="realPic1" src="/Public/showimgbj.jpg"/> <input name="realPicFile1" id="realPicFile1" type="file" onchange="ajaxFileUpload('realPicFile1','realPic1','hiddenImgValue1')" style='display:none'/> <input type=button onclick="upImg('realPicFile1')" value="上傳" /> <span class="errormsg"> <form:errors path="worksImg1" /> </span> </td> </tr> <tr> <td align="right">作品圖2:</td> <td align="left"> <img src="/Public/media/image/loading2.gif" id="loading" style="display: none;"> <img id="realPic2" src="/Public/showimgbj.jpg"/> <input name="realPicFile2" id="realPicFile2" type="file" onchange="ajaxFileUpload('realPicFile2','realPic2','hiddenImgValue2')" style='display:none'/> <input type=button onclick="upImg('realPicFile2')" value="上傳" /> <span class="errormsg"> <form:errors path="worksImg2" /> </span> </td> </tr> <tr> <td align="right">作品圖3:</td> <td align="left"> <img src="/Public/media/image/loading2.gif" id="loading" style="display: none;"> <img id="realPic3" src="/Public/showimgbj.jpg"/> <input name="realPicFile3" id="realPicFile3" type="file" onchange="ajaxFileUpload('realPicFile3','realPic3','hiddenImgValue3')" style='display:none'/> <input type=button onclick="upImg('realPicFile3')" value="上傳" /> <span class="errormsg"><form:errors path="worksImg3" /> </span> </td> </tr> <tr> <td></td> <td><input name="" type="submit" value="提交" /></td> </tr> </table> </div> </form:form> </div> <div id="errorMsgDiv"></div> <script src="/Public/media/js/jquery-1.10.1.min.js" type="text/javascript"></script> <script src="/Public/media/js/jquery-migrate-1.2.1.min.js" type="text/javascript"></script> <script src="/Public/media/js/bootstrap.min.js" type="text/javascript"></script> <script src="/Public/media/js/jquery.gritter.js" type="text/javascript"></script> <script src="/Public/media/js/app.js" type="text/javascript"></script> <script src="/Public/media/css/new/ajaxfileupload.js" type="text/javascript"></script> <script> jQuery(document).ready(function() { App.init(); // initlayout and core plugins }); </script> <script> function upImg(fileID){ $("#"+fileID).click(); } function ajaxFileUpload(fileID,imgID,hiddenImgValue) { /*var file = $("#"+hiddenImgValue).val(); if(!/\.(jpg|png|JPG|PNG)$/.test(file)){ Error("不支援的圖片格式.圖片型別必須是.jpg,png格式."); return false; }*/ $.ajaxFileUpload({ url : '${pageContext.request.contextPath}/workConfig/uploadOnePic?inputId='+fileID, secureuri : false, fileElementId : fileID, dataType : 'json', success : function(data, status){ $("#"+imgID).attr("src", data.result); $("#"+hiddenImgValue).val(data.result); //$(this).val(data.result); //console.log($('#realPicFile')); }, error : function(data, status, e){ alert(e); //Error(e); } }); return true; } </script> </body> </html>
controller程式碼
@RequestMapping("/uploadOnePic") @ResponseBody public AjaxResultDomain fileUpload(String inputId, MultipartHttpServletRequest request) { try { // 拿到檔案 MultipartFile realPicFile = request.getFile(inputId); // 準備好路徑引數 String uploadImagesSavePath = pathUtil.getYgbhUploadImagesDiskFolderPath(request); String urlRootPath = pathUtil.getYgbhUploadImagesUrlFolderPath(); List<MultipartFile> files = new ArrayList<MultipartFile>(); files.add(realPicFile); // 儲存+壓縮 String fileName = MultipartFileUtil.saveAndConstrictMultipartFiles(files, uploadImagesSavePath, urlRootPath) .get(0); String fileUrl = urlRootPath + fileName; AjaxResultDomain d = new AjaxResultDomain(); d.setResult(fileUrl); return d; } catch (Exception e) { e.printStackTrace(); } return null; }
注意,ajax拿到後臺返回的值data以後,使用data.result給圖片地址賦值而不是直接用data賦值。原因是,如果後臺直接將圖片地址作為String字串返回給前臺的話,js會將圖片地址辨認為是一個正規表示式並報錯。
所以,對付js這麼靈活的東西,能繞開就繞開,否則坑很深。不跟它糾結,直接用一個object返回來,然後取object的屬性。