spring實現文件上傳(圖片解析)
阿新 • • 發佈:2017-08-02
handle exc 所有 sub str [] sys script ota
合抱之木,生於毫末,千裏之行,始於足下,要想了解spring的文件上傳功能,首先要知道spring是通過流的方式將文件進行解析,然後上傳。那麽是不是所有需要用的文件上傳的地方都要寫一遍文件解析器呢?
放心,spring這個大管家已經為我們做好了一切!
我們只需要在spring的配置文件中加入下面代碼:
<!-- 文件上傳解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:maxUploadSize="152400" p:defaultEncoding="utf-8"> <!-- <property name="defaultEncoding" value="utf-8"></property> --> </bean> <!-- SpringMVC在超出上傳文件限制時,會拋出org.springframework.web.multipart.MaxUploadSizeExceededException --> <!-- 該異常是SpringMVC在檢查上傳的文件信息時拋出來的,而且此時還沒有進入到Controller方法中--> <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- 遇到MaxUploadSizeExceededException異常時,自動跳轉到/WEB-INF/jsp/error_fileupload.jsp頁面--> <prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">error_fileupload</prop> </props> </property> </bean>
我們就不用再去在文件的解析上絞盡腦汁了,只需要專註於業務層面的邏輯就好了,是不是很簡單?
接下來我們看一個小例子:
html前端代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>Insert title here</title> </head> <body> <form action="<%=request.getContextPath()%>/user/add" method="post" enctype="multipart/form-data"> <h1>新增用戶</h1> <table> <tr> <td>用戶名:</td> <td> <input type="text" name="userName" value="${user.userName }" /> </td> </tr> <tr> <td>密碼:</td> <td> <input type="text" name="password" value="${user.userPass }" /> </td> </tr> <tr> <td>頭像:</td> <td> <input type="file" name="photo" /> </td> </tr> <tr> <td></td> <td> <input type="submit" value="上傳" /> </td> </tr> </table> </form> </body> </html>
大家有沒有註意到以上代碼的form表頭中有一行代碼:
enctype="multipart/form-data"
沒錯,想要上傳二進制文件,該表頭屬性必不可少。
controller控制層代碼:
package com.wskj.springmvc.controller; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import com.wskj.springmvc.pojo.UserInfo; @Controller @RequestMapping("/user") public class UserController { @RequestMapping(value="/add", method=RequestMethod.GET) public String addUser(){ return "user/add"; } @RequestMapping(value="/add", method=RequestMethod.POST) public String addUser(Model model, UserInfo user, @RequestParam(name="photo", required=false) MultipartFile photo, HttpServletRequest request) throws IOException{ //對文件進行處理 //判斷用戶是否上傳了文件 //MultipartFile.getSize() : 獲取文件的大小(字節:byte) 1024byte = 1kb 1024kb=1mb GB TB PB if(photo.isEmpty() == false && photo.getSize() > 0){ //獲取文件的名稱 String name = photo.getName();//photo String fileName = photo.getOriginalFilename();//mydata.jpg //獲取文件擴展名 String extension = fileName.substring(fileName.lastIndexOf(".")); byte[] data = photo.getBytes();//字節數組 String contentType = photo.getContentType(); /** * 擴展名 Content-Type * .txt text/plain * .jpg image/jpeg * .mp3 audio/mp3 * .mp4 video/mpeg4 */ photo.getInputStream();//獲取文件輸入流 //保存到磁盤 //保存的路徑 //不是 -》 F:\java\workspace\spring\springmvc_fileupload_20170401\WebContent\files //是 -》 x:\apache tomcat-7\webapps\appName\files String savedPath = request.getServletContext().getRealPath("files");//獲取files目錄的絕對路徑 String filePath = savedPath + "/" + fileName; //將文件寫入磁盤 photo.transferTo(new File(filePath)); //設置UserInfo.headerPhoto user.setHeaderPhotoUrl("files/"+fileName); model.addAttribute("headerUrl", user.getHeaderPhotoUrl()); } model.addAttribute("user", user); return "user/success"; } @RequestMapping(value="/add2", method=RequestMethod.GET) public String addUser2(){ return "user/add2"; } @RequestMapping(value="/add2", method=RequestMethod.POST) public String addUser2(Model model, UserInfo user, @RequestParam(name="photos", required=false) MultipartFile[] photos, HttpServletRequest request) throws IOException{ //對文件進行處理 if(photos != null && photos.length>0){ List<String> photoUrls = new ArrayList<String>(); for(MultipartFile photo : photos){ //判斷用戶是否上傳了文件 //MultipartFile.getSize() : 獲取文件的大小(字節:byte) 1024byte = 1kb 1024kb=1mb GB TB PB if(photo.isEmpty() == false && photo.getSize() > 0){ //獲取文件的名稱 String name = photo.getName();//photo String fileName = photo.getOriginalFilename();//mydata.jpg //獲取文件擴展名 String extension = fileName.substring(fileName.lastIndexOf(".")); byte[] data = photo.getBytes();//字節數組 String contentType = photo.getContentType(); /** * 擴展名 Content-Type * .txt text/plain * .jpg image/jpeg * .mp3 audio/mp3 * .mp4 video/mpeg4 */ photo.getInputStream();//獲取文件輸入流 //保存到磁盤 //保存的路徑 //不是 -》 F:\java\workspace\spring\springmvc_fileupload_20170401\WebContent\files //是 -》 x:\apache tomcat-7\webapps\appName\files String savedPath = request.getServletContext().getRealPath("files");//獲取files目錄的絕對路徑 String filePath = savedPath + "/" + fileName; //將文件寫入磁盤 photo.transferTo(new File(filePath)); //設置UserInfo.headerPhoto photoUrls.add("files/"+fileName); } } model.addAttribute("headerUrl", photoUrls); } model.addAttribute("user", user); return "user/success2"; } }
後臺根據前段的name屬性接收參數,二進制文件類型為
MultipartFile,如果需要接收多個文件,只需要設置成集合然後遍歷即可。
接下來是上傳成功前段回顯的jsp代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>Insert title here</title> </head> <body> <dl> <dt>用戶名:</dt> <dd>${user.userName }</dd> <dt>頭像:</dt> <dd> <img style="max-width:300px;max-height:200px;" src="<%=request.getContextPath() %>/${headerUrl}" /> </dd> </dl> </body> </html>
至此,最基礎的文件上傳測試成功。
但是,在實際項目中,我們可能只是需要啟用一個div來進行文件的異步上傳,這時我們可以使用html5的新特性formdata實現ajax的提交。
具體代碼如下:
jsp前端代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>Insert title here</title> <script type="text/javascript" src="<%= request.getContextPath()%>/static/jquery-1.10.2.js"></script> <script type="text/javascript"> $(function(){ $("#btnupload").click(function(){ var formdata = new FormData(document.getElementById("form1"));//可以上傳文件 //var formdata = $("#form1").serializeArray();//無法上傳文件的 alert(formdata); var url ="<%= request.getContextPath()%>/upload/demo1"; $.ajax({ url:url, data:formdata, //name=zhangsan&age=50 {} contentType: false,//默認: "application/x-www-form-urlencoded" processData: false,//設置 processData 選項為 false,防止自動轉換數據格式 type:"post", dataType:"json", success:function(data){ alert(data); }, error:function(er){ alert(er.responseText); } }); }); }); </script> </head> <body> <h1>使用Html5提供的FormData實現ajax提交</h1> <h3>瀏覽器必須支持html5,如果是IE6 - IE8,那就洗洗睡吧...</h3> <form id="form1"> 文件名:<input type="text" name="fileName" /> 文件:<input type="file" name="myfile" /> <input id="btnupload" type="button" value="ajax上傳文件" /> </form> </body> </html>
我們可以看見,只需要給要提交的form表單指定一個唯一標識id即可,是不是很方便?
後臺controller接收代碼:
package com.wskj.uploadfile.controller; import java.io.File; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; @Controller @RequestMapping("/upload") public class AjaxController { @RequestMapping(value="/demo1", method=RequestMethod.GET) public String demo1(){ return "upload/demo1"; } @RequestMapping(value="/demo1", method=RequestMethod.POST) @ResponseBody public boolean demo1(String fileName, MultipartFile myfile, HttpServletRequest request) throws IllegalStateException, IOException{ String path = request.getServletContext().getRealPath("files"); path += "/" + myfile.getOriginalFilename(); File file = new File(path); myfile.transferTo(file); System.out.println(fileName+" - 上傳成功"); return true; } }
另外還可以使用jquery.form.js實現ajax的上傳:
前段jsp代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>Insert title here</title> <script type="text/javascript" src="<%= request.getContextPath()%>/static/jquery-1.10.2.js"></script> <script type="text/javascript" src="<%= request.getContextPath()%>/static/jquery.form.js"></script> <script type="text/javascript"> $(function(){ $("#btnupload").click(function(){ var url ="<%= request.getContextPath()%>/upload/demo2"; $("#form1").ajaxSubmit({ type:‘post‘, url:url, clearForm:true,//清空所有表單元素的值 resetForm:true,//重置所有表單元素的值 success:function(data){ alert(data); }, error:function(XmlHttpRequest,textStatus,errorThrown){ alert("上傳失敗了"); } }); }); }); </script> </head> <body> <h1>使用jquery.form.js實現ajax文件上傳</h1> <h3>對瀏覽器沒有限制,盡情使用吧騷年們...</h3> <form id="form1"> 文件名:<input type="text" name="fileName" value="我的頭像" /> 文件:<input type="file" name="myfile" /> <input id="btnupload" type="button" value="ajax上傳文件" /> </form> </body> </html>
後臺controller接收代碼:
package com.wskj.uploadfile.controller; import java.io.File; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; @Controller @RequestMapping("/upload") public class AjaxController { @RequestMapping(value="/demo2", method=RequestMethod.GET) public String demo2(){ return "upload/demo2"; } @RequestMapping(value="/demo2", method=RequestMethod.POST) @ResponseBody public boolean demo2(String fileName, MultipartFile myfile, HttpServletRequest request) throws IllegalStateException, IOException{ String path = request.getServletContext().getRealPath("files"); path += "/" + myfile.getOriginalFilename(); File file = new File(path); myfile.transferTo(file); System.out.println(fileName+" - 上傳成功"); return true; } }
當然,使用這兩種方法也必須在spring中配置文件上傳解析器,這個是上傳二進制文件的前提。
spring實現文件上傳(圖片解析)