SpringMVC 文件上傳下載
文件上傳
文件上傳是項目開發中最常見的功能。為了能上傳文件,必須將表單的method設置為POST,並將enctype設置為multipart/form-data。只有在這樣的情況下,瀏覽器才會把用戶選擇的文件以二進制數據發送給服務器。
一旦設置了enctype為multipart/form-data,瀏覽器即會采用二進制流的方式來處理表單數據,而對於文件上傳的處理則涉及在服務器端解析原始的HTTP響應。在2003年,Apache Software Foundation發布了開源的Commons FileUpload組件,其很快成為Servlet/JSP程序員上傳文件的最佳選擇。
Servlet3.0規範已經提供方法來處理文件上傳,但這種上傳需要在Servlet中完成。而Spring MVC則提供了更簡單的封裝。
Spring MVC為文件上傳提供了直接的支持,這種支持是用即插即用的MultipartResolver實現的。Spring MVC使用Apache Commons FileUpload技術實現了一個MultipartResolver實現類:CommonsMultipartResolver。因此,SpringMVC的文件上傳還需要依賴Apache Commons FileUpload的組件。
MultipartFile對象
Spring MVC會將上傳的文件綁定到MultipartFile對象中。MultipartFile提供了獲取上傳文件內容、文件名等方法。通過transferTo()方法還可以將文件存儲到硬件中,MultipartFile對象中的常用方法如下:
- byte[] getBytes():獲取文件數據
- String getContentType[]:獲取文件MIME類型,如image/jpeg等
- InputStream getInputStream():獲取文件流
- String getName():獲取表單中文件組件的名字
- String getOriginalFilename():獲取上傳文件的原名
- Long getSize():獲取文件的字節大小,單位為byte
- boolean isEmpty():是否有上傳文件
- void transferTo(File dest):將上傳文件保存到一個目錄文件中
文件下載
在頁面給出了一個超鏈接,該鏈接href的屬性等於要下載文件的文件名,就可以實現文件下載了。
接收頁面傳遞的文件名filename後,使用Apache Commons FileUpload組件的FileUtils讀取項目的上傳文件,並將其構建成ResponseEntity對象返回客戶端下載。
使用ResponseEntity對象,可以很方便的定義返回的HttpHeaders和HttpStatus。上面代碼中的MediaType,代表的是Internet Media Type,即互聯網媒體類型,也叫做MIME類型。在Http協議消息頭中,使用Content-Type來表示具體請求中的媒體類型信息。HttpStatus類型代表的是Http協議中的狀態。有關MediaType和HttpStatus類可以參考Spring MVC的API文檔。
pom.xml增加
<!-- 文件上傳組件 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3</version>
</dependency>
創建uploadForm.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>
<h2>文件上傳</h2>
<form action="${pageContext.request.contextPath}/mvc/upload" enctype="multipart/form-data" method="post">
<table>
<tr>
<td>文件描述:</td>
<td><input type="text" name="description"></td>
</tr>
<tr>
<td>請選擇文件:</td>
<td><input type="file" name="file"></td>
</tr>
<tr>
<td><input type="submit" value="上傳"></td>
</tr>
</table>
</form>
</body>
</html>
創建uploadForm2.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>
<h2>用戶註冊</h2>
<form action="${pageContext.request.contextPath}/mvc/upload2" enctype="multipart/form-data" method="post">
<table>
<tr>
<td>用戶名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>請上傳頭像:</td>
<td><input type="file" name="image"></td>
</tr>
<tr>
<td><input type="submit" value="註冊"></td>
</tr>
</table>
</form>
</body>
</html>
創建userInfo.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>
<h3>文件下載</h3>
<a href="download?filename=${requestScope.user.image.originalFilename}"> ${requestScope.user.image.originalFilename }
</a>
</body>
</html>
springmvc-servlet.xml添加
SpringMVC上下文中默認沒有裝配MultipartResolver,因此默認情況下其不能處理文件上傳工作。如果想使用Spring的文件上傳功能,則需要在上下文中配置MultipartResolver
<!-- 文件上傳的配置 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1048576" /><!-- 上傳文件大小上限,單位為字節(1MB) -->
<property name="defaultEncoding" value="UTF-8" /><!-- 請求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取表單的內容,默認為ISO-8859-1 -->
</bean>
創建User2.java對象
使用對象接受接收上傳文件,必須要實現序列化接口
package com.xc.entity;
import java.io.Serializable;
import org.springframework.web.multipart.MultipartFile;
public class User2 implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private MultipartFile image;
public User2() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MultipartFile getImage() {
return image;
}
public void setImage(MultipartFile image) {
this.image = image;
}
}
創建UploadController.java
package com.xc.controller;
import java.io.File;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.FileUtils;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import com.xc.entity.User2;
@Controller
@RequestMapping("/mvc")
public class UploadController {
// 上傳文件會自動綁定到MultipartFile中
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String upload(HttpServletRequest request, @RequestParam("description") String description,
@RequestParam("file") MultipartFile multipartFile) throws Exception {
System.out.println(description);
if (!multipartFile.isEmpty()) {// 是否有上傳文件
// 上傳文件路徑
// String path = request.getServletContext().getRealPath("/upload/");
// 得到上傳文件的保存目錄,將上傳的文件存放於WEB-INF目錄下,不允許外界直接訪問,保證上傳文件的安全
String path = request.getServletContext().getRealPath("/WEB-INF/upload");
System.out.println(path);
String filename = multipartFile.getOriginalFilename();// 獲取上傳文件的原名
File filepath = new File(path, filename);
System.out.println(filepath);
// 判斷路徑是否存在,如果不存在就創建一個
if (!filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
multipartFile.transferTo(new File(path + File.separator + filename));// 將上傳文件保存到一個目標文件當中
return "success";
} else {
return "error";
}
}
@RequestMapping(value = "/upload2")
public String register(HttpServletRequest request, @ModelAttribute User2 user, Model model) throws Exception {
System.out.println(user.getName());
// 如果文件不為空,寫入上傳路徑
if (!user.getImage().isEmpty()) {
// 上傳文件路徑
String path = request.getServletContext().getRealPath("/WEB-INF/upload");
// 上傳文件名
String filename = user.getImage().getOriginalFilename();
File filepath = new File(path, filename);
// 判斷路徑是否存在,如果不存在就創建一個
if (!filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
// 將上傳文件保存到一個目標文件當中
user.getImage().transferTo(new File(path + File.separator + filename));
// 將用戶添加到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("/WEB-INF/upload/");
File file = new File(path + File.separator + filename);
HttpHeaders headers = new HttpHeaders();
// 下載顯示的文件名,解決中文名稱亂碼問題
String downloadFielName = new String(filename.getBytes("UTF-8"), "iso-8859-1");
// 通知瀏覽器以attachment(下載方式)打開圖片
headers.setContentDispositionFormData("attachment", downloadFielName);
// application/octet-stream : 二進制流數據(最常見的文件下載)。
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
}
}
參考文章:
Spring MVC 實現文件的上傳和下載
SpringMVC 文件上傳下載