您好,登錄后才能下訂單哦!
這篇文章給大家介紹利用SpringMVC如何實(shí)現(xiàn)一個(gè)文件上傳下載功能,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
文件上傳
文件上傳是項(xiàng)目開(kāi)發(fā)中最常見(jiàn)的功能。為了能上傳文件,必須將表單的method設(shè)置為POST,并將enctype設(shè)置為multipart/form-data。只有在這樣的情況下,瀏覽器才會(huì)把用戶(hù)選擇的文件以二進(jìn)制數(shù)據(jù)發(fā)送給服務(wù)器。
一旦設(shè)置了enctype為multipart/form-data,瀏覽器即會(huì)采用二進(jìn)制流的方式來(lái)處理表單數(shù)據(jù),而對(duì)于文件上傳的處理則涉及在服務(wù)器端解析原始的HTTP響應(yīng)。在2003年,Apache Software Foundation發(fā)布了開(kāi)源的Commons FileUpload組件,其很快成為Servlet/JSP程序員上傳文件的最佳選擇。
Servlet3.0規(guī)范已經(jīng)提供方法來(lái)處理文件上傳,但這種上傳需要在Servlet中完成。而SpringMVC則提供了更簡(jiǎn)單的封裝。
SpringMVC為文件上傳提供了直接的支持,這種支持是用即插即用的MultipartResolver實(shí)現(xiàn)的。SpringMVC使用Apache Commons FileUpload技術(shù)實(shí)現(xiàn)了一個(gè)MultipartResolver實(shí)現(xiàn)類(lèi):CommonsMultipartResolver。因此,SpringMVC的文件上傳還需要依賴(lài)Apache Commons FileUpload的組件。
本項(xiàng)目作為測(cè)試案例,在此我就不創(chuàng)建Maven項(xiàng)目了,我直接創(chuàng)建的是一個(gè)Dynamic Web Project(動(dòng)態(tài)的web項(xiàng)目),采用Tomcat 8作為web服務(wù)器,我們需要在項(xiàng)目中引入以下jar包,如下圖:
下面我們?cè)赪ebContent/WEB-INF下創(chuàng)建一個(gè)content文件夾,用于放文件的上傳、下載等jsp文件,下面我們創(chuàng)建uploadForm.jsp文件,演示SpringMVC的文件上傳:
<%@ 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>文件上傳</title> </head> <body> <h3>文件上傳</h3> <form action="upload" enctype="multipart/form-data" method="post"> <table> <tr> <td>文件描述:</td> <td><input type="text" name="description"></td> </tr> <tr> <td>請(qǐng)選擇文件:</td> <td><input type="file" name="file"></td> </tr> <tr> <td><input type="submit" value="上傳"></td> </tr> </table> </form> </body> </html>
負(fù)責(zé)上傳文件的表單和一般表單有一些區(qū)別,負(fù)責(zé)上傳文件的表單的編碼類(lèi)型必須是“multipart/form-data”。
我們?cè)賡rc下創(chuàng)建一個(gè)包“cn.edu.jseti.controller”,然后創(chuàng)建一個(gè)FileUploadController類(lèi),用于實(shí)現(xiàn)文件的上傳和下載功能。以下是負(fù)責(zé)上傳文件的表單功能代碼:
//上傳文件會(huì)自動(dòng)綁定到MultipartFile中 @RequestMapping(value="/upload",method=RequestMethod.POST) public String upload(HttpServletRequest request, @RequestParam("description") String description, @RequestParam("file") MultipartFile file) throws Exception { System.out.println(description); //如果文件不為空,寫(xiě)入上傳路徑 if(!file.isEmpty()) { //上傳文件路徑 String path = request.getServletContext().getRealPath("/images/"); //上傳文件名 String filename = file.getOriginalFilename(); File filepath = new File(path,filename); //判斷路徑是否存在,如果不存在就創(chuàng)建一個(gè) if (!filepath.getParentFile().exists()) { filepath.getParentFile().mkdirs(); } //將上傳文件保存到一個(gè)目標(biāo)文件當(dāng)中 file.transferTo(new File(path + File.separator + filename)); return "success"; } else { return "error"; } }
SpringMVC會(huì)將上傳的文件綁定到MultipartFile對(duì)象中。MultipartFile提供了獲取上傳文件內(nèi)容、文件名等方法。通過(guò)transferTo()方法還可以將文件存儲(chǔ)到硬件中,MultipartFile對(duì)象中的常用方法如下:
SpringMVC上下文中默認(rèn)沒(méi)有裝配MultipartResolver,因此默認(rèn)情況下其不能處理文件上傳工作。如果想使用spring的文件上傳功能,則需要在上下文中配置MultipartResolver。在springmvc-config.xml進(jìn)行配置文件如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- spring可以自動(dòng)去掃描base-pack下面的包或者子包下面的java文件, 如果掃描到有Spring的相關(guān)注解的類(lèi),則把這些類(lèi)注冊(cè)為Spring的bean --> <context:component-scan base-package="cn.edu.jseti.controller"/> <!-- 視圖解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前綴 --> <property name="prefix"> <value>/WEB-INF/content/</value> </property> <!-- 后綴 --> <property name="suffix"> <value>.jsp</value> </property> </bean> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 上傳文件大小上限,單位為字節(jié)(10MB) --> <property name="maxUploadSize"> <value>10485760</value> </property> <!-- 請(qǐng)求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取表單的內(nèi)容,默認(rèn)為ISO-8859-1 --> <property name="defaultEncoding"> <value>UTF-8</value> </property> </bean> </beans>
部署FileUpload這個(gè)Web應(yīng)用,在瀏覽器中輸入如下URL來(lái)測(cè)試應(yīng)用: http://localhost:8088/FileUpload/uploadForm
輸入文件描述信息并選擇上傳文件,如下圖:
點(diǎn)上傳按鈕,這是已將上傳的文件通過(guò)二進(jìn)制保存到web服務(wù)器上去了,如下圖:
使用對(duì)象接收上傳文件
上面我們通過(guò)案例演示了SpringMVC上傳文件,接下來(lái),我們演示使用對(duì)象接收上傳文件。
在實(shí)際項(xiàng)目的開(kāi)發(fā)中,很多時(shí)候上傳的文件會(huì)作為對(duì)象的屬性被保存。SpringMVC的處理也非常的簡(jiǎn)單。
下面我們?cè)赾ontent文件夾創(chuàng)建registerForm.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>用戶(hù)注冊(cè)</title> </head> <body> <h3>用戶(hù)注冊(cè)</h3> <form action="register" enctype="multipart/form-data" method="post"> <table> <tr> <td>用戶(hù)名:</td> <td><input type="text" name="username"></td> </tr> <tr> <td>請(qǐng)上傳頭像:</td> <td><input type="file" name="image"></td> </tr> <tr> <td><input type="submit" value="注冊(cè)"></td> </tr> </table> </form> </body> </html>
我們?cè)趕rc下面創(chuàng)建一個(gè)名叫“cn.edu.jseti.domain”包,然后再創(chuàng)建一個(gè)User類(lèi),必須要實(shí)現(xiàn)序列化接口,如下案例代碼:
package cn.edu.jseti.domain; import java.io.Serializable; import org.springframework.web.multipart.MultipartFile; /** * 博客:http://blog.csdn.net/qian_ch * @author Cody * @version V1.0 */ //域?qū)ο螅瑢?shí)現(xiàn)序列化接口 public class User implements Serializable{ private String username; private MultipartFile image; public User() { super(); } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public MultipartFile getImage() { return image; } public void setImage(MultipartFile image) { this.image = image; } }
我們?cè)趧偛艅?chuàng)建的FileUploadController類(lèi)繼續(xù)寫(xiě)用于接收文件的上傳和下載功能。以下是負(fù)責(zé)接收文件的表單功能代碼:
@RequestMapping(value="/register") public String register(HttpServletRequest request, @ModelAttribute User user, Model model) throws Exception { System.out.println(user.getUsername()); //如果文件不為空,寫(xiě)入上傳路徑 if(!user.getImage().isEmpty()) { //上傳文件路徑 String path = request.getServletContext().getRealPath("/images/"); //上傳文件名 String filename = user.getImage().getOriginalFilename(); File filepath = new File(path,filename); //判斷路徑是否存在,如果不存在就創(chuàng)建一個(gè) if (!filepath.getParentFile().exists()) { filepath.getParentFile().mkdirs(); } //將上傳文件保存到一個(gè)目標(biāo)文件當(dāng)中 user.getImage().transferTo(new File(path + File.separator + filename)); //將用戶(hù)添加到model model.addAttribute("user", user); return "userInfo"; } else { return "error"; } }
在content文件夾下創(chuàng)建userInfo.jsp文件,該頁(yè)面主要是文件的下載頁(yè)面,如下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>文件下載</title> </head> <body> <h4>文件下載</h4> <a href="download?filename=${requestScope.user.image.originalFilename}" rel="external nofollow" > ${requestScope.user.image.originalFilename } </a> </body> </html>
在瀏覽器中輸入如下URL來(lái)測(cè)試應(yīng)用: http://localhost:8088/FileUpload/registerForm
輸入用戶(hù)名并上傳剛才上傳的文件。如下圖:
單擊“注冊(cè)”按鈕上傳文件,然后就會(huì)跳轉(zhuǎn)到下載頁(yè)面。如下圖:
文件下載
上面我們通過(guò)案例演示了使用對(duì)象接收上傳文件,接下來(lái),我們演示SpringMVC的下載文件。
文件下載比較簡(jiǎn)單,直接在頁(yè)面給出了一個(gè)超鏈接,該鏈接href的屬性等于要下載文件的文件名,就可以實(shí)現(xiàn)文件下載了。但是如果該文件的文件名為中文文件名,在某些早起的瀏覽器上就會(huì)導(dǎo)致下載失??;如果使用最新的Firefox、Chrome、Opera、Safari則都可以正常下載文件名為中文的文件了。
SpringMVC提供了一個(gè)ResponseEntity類(lèi)型,使用它可以很方便地定義返回的HttpHeaders和HttpStatus。以下代碼演示文件的下載功能:
@RequestMapping(value="/download") public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename, Model model)throws Exception { //下載文件路徑 String path = request.getServletContext().getRealPath("/images/"); File file = new File(path + File.separator + filename); HttpHeaders headers = new HttpHeaders(); //下載顯示的文件名,解決中文名稱(chēng)亂碼問(wèn)題 String downloadFielName = new String(filename.getBytes("UTF-8"),"iso-8859-1"); //通知瀏覽器以attachment(下載方式)打開(kāi)圖片 headers.setContentDispositionFormData("attachment", downloadFielName); //application/octet-stream : 二進(jìn)制流數(shù)據(jù)(最常見(jiàn)的文件下載)。 headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED); }
download處理方法接收頁(yè)面?zhèn)鬟f的文件名filename后,使用Apache Commons FileUpload組件的FileUtils讀取項(xiàng)目的上傳文件,并將其構(gòu)建成ResponseEntity對(duì)象返回客戶(hù)端下載。
使用ResponseEntity對(duì)象,可以很方便的定義返回的HttpHeaders和HttpStatus。上面代碼中的MediaType,代表的是Internet Media Type,即互聯(lián)網(wǎng)媒體類(lèi)型,也叫做MIME類(lèi)型。在Http協(xié)議消息頭中,使用Content-Type來(lái)表示具體請(qǐng)求中的媒體類(lèi)型信息。HttpStatus類(lèi)型代表的是Http協(xié)議中的狀態(tài)。有關(guān)MediaType和HttpStatus類(lèi)可以參考SpringMVC的API文檔。
點(diǎn)擊下載頁(yè)面的超鏈接,顯示文件正在下載,如下圖所示:
單擊“瀏覽”按鈕,可以選擇下載文件的保存路徑,然后單擊“確定”按鈕,文件就會(huì)順利的下載并保存。
本文中的一些功能案例代碼和配置文件不是很完整,下面附上完整代碼:
FileUploadController類(lèi)完整的代碼如下:
package cn.edu.jseti.controller; import java.io.File; import javax.servlet.http.HttpServletRequest; import org.apache.commons.io.FileUtils; import cn.edu.jseti.domain.User; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; 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; /** * @author Cody * @version V1.0 */ @Controller public class FileUploadController { @RequestMapping(value="/{formName}") public String loginForm(@PathVariable String formName) { // 動(dòng)態(tài)跳轉(zhuǎn)頁(yè)面 return formName; } //上傳文件會(huì)自動(dòng)綁定到MultipartFile中 @RequestMapping(value="/upload",method=RequestMethod.POST) public String upload(HttpServletRequest request, @RequestParam("description") String description, @RequestParam("file") MultipartFile file) throws Exception { System.out.println(description); //如果文件不為空,寫(xiě)入上傳路徑 if(!file.isEmpty()) { //上傳文件路徑 String path = request.getServletContext().getRealPath("/images/"); //上傳文件名 String filename = file.getOriginalFilename(); File filepath = new File(path,filename); //判斷路徑是否存在,如果不存在就創(chuàng)建一個(gè) if (!filepath.getParentFile().exists()) { filepath.getParentFile().mkdirs(); } //將上傳文件保存到一個(gè)目標(biāo)文件當(dāng)中 file.transferTo(new File(path + File.separator + filename)); return "success"; } else { return "error"; } } @RequestMapping(value="/register") public String register(HttpServletRequest request, @ModelAttribute User user, Model model) throws Exception { System.out.println(user.getUsername()); //如果文件不為空,寫(xiě)入上傳路徑 if(!user.getImage().isEmpty()) { //上傳文件路徑 String path = request.getServletContext().getRealPath("/images/"); //上傳文件名 String filename = user.getImage().getOriginalFilename(); File filepath = new File(path,filename); //判斷路徑是否存在,如果不存在就創(chuàng)建一個(gè) if (!filepath.getParentFile().exists()) { filepath.getParentFile().mkdirs(); } //將上傳文件保存到一個(gè)目標(biāo)文件當(dāng)中 user.getImage().transferTo(new File(path + File.separator + filename)); //將用戶(hù)添加到model model.addAttribute("user", user); return "userInfo"; } else { return "error"; } } @RequestMapping(value="/download") public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename, Model model)throws Exception { //下載文件路徑 String path = request.getServletContext().getRealPath("/images/"); File file = new File(path + File.separator + filename); HttpHeaders headers = new HttpHeaders(); //下載顯示的文件名,解決中文名稱(chēng)亂碼問(wèn)題 String downloadFielName = new String(filename.getBytes("UTF-8"),"iso-8859-1"); //通知瀏覽器以attachment(下載方式)打開(kāi)圖片 headers.setContentDispositionFormData("attachment", downloadFielName); //application/octet-stream : 二進(jìn)制流數(shù)據(jù)(最常見(jiàn)的文件下載)。 headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED); } }
文件上傳成功的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>測(cè)試文件上傳</title> </head> <body> 恭喜,您的上傳文件成功! </body> </html>
文件上傳失敗的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>測(cè)試文件上傳</title> </head> <body> 上傳文件失敗! </body> </html>
web.xml的配置文件:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>MultipartFileTest</display-name> <!-- 定義Spring MVC的前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/springmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 讓Spring MVC的前端控制器攔截所有請(qǐng)求 --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 編碼過(guò)濾器 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
關(guān)于利用SpringMVC如何實(shí)現(xiàn)一個(gè)文件上傳下載功能就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。