1. 概述
在之前的教程中,我們介紹了表單處理的基礎知識,並探索了 Spring MVC 中的表單標籤庫。
在本教程中,我們將重點介紹 Spring 為 Web 應用程序提供的 多部分(文件上傳)支持。
Spring 允許我們通過可插拔的 MultipartResolver 對象啓用此多部分支持。框架提供了一個 MultipartResolver 實現,用於與 Servlet 3.0 多部分請求解析一起使用。
配置了 MultipartResolver 後,我們將看到如何上傳單個文件和多個文件。
我們還將涉及 Spring Boot。
2. 使用 Servlet 3.0 的配置
為了使用 Servlet 3.0 的多部分解析功能,我們需要配置應用程序的幾個部分。
首先,我們需要在 DispatcherServlet 的註冊中設置一個 MultipartConfigElement:
public class MainWebAppInitializer implements WebApplicationInitializer {
private static final String TMP_FOLDER = "/tmp";
private static final int MAX_UPLOAD_SIZE = 5 * 1024 * 1024;
@Override
public void onStartup(ServletContext sc) throws ServletException {
ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(
new GenericWebApplicationContext()));
appServlet.setLoadOnStartup(1);
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(TMP_FOLDER,
MAX_UPLOAD_SIZE, MAX_UPLOAD_SIZE * 2L, MAX_UPLOAD_SIZE / 2);
appServlet.setMultipartConfig(multipartConfigElement);
}
}在 <em>MultipartConfigElement</em> 對象中,我們已配置了存儲位置、單個文件最大大小、單個請求的最大文件大小(對於單個請求中的多文件)以及文件上傳進度刷新到存儲位置的閾值。
完成這些配置後,我們可以將 <em>StandardServletMultipartResolver</em> 添加到我們的 Spring 配置中:
@Bean
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}3. 上傳文件
為了上傳我們的文件,我們可以構建一個簡單的表單,其中我們使用 HTML 標籤 <em type=’file’</em>>。
無論我們選擇哪種上傳處理配置,都需要將表單的 encoding 屬性設置為 <em multipart/form-data</em>>。
這讓瀏覽器知道如何編碼表單:
<form:form method="POST" action="/spring-mvc-xml/uploadFile" enctype="multipart/form-data">
<table>
<tr>
<td><form:label path="file">Select a file to upload</form:label></td>
<td><input type="file" name="file" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
</tr>
</table>
</form>要存儲上傳的文件,我們可以使用 MultipartFile 變量。
我們可以從請求參數中檢索此變量,位於控制器的方法的內部:
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public String submit(@RequestParam("file") MultipartFile file, ModelMap modelMap) {
modelMap.addAttribute("file", file);
return "fileUploadView";
}
MultipartFile 類提供對上傳文件信息的訪問,包括文件名、文件類型等。
我們可以使用一個簡單的 HTML 頁面來顯示這些信息:
<h2>Submitted File</h2>
<table>
<tr>
<td>OriginalFileName:</td>
<td>${file.originalFilename}</td>
</tr>
<tr>
<td>Type:</td>
<td>${file.contentType}</td>
</tr>
</table>當項目在本地運行時,示例表單可以通過以下網址訪問:http://localhost:8080/spring-mvc-java/fileUpload。
4. 上傳多個文件
為了在單個請求中上傳多個文件,我們將多個輸入文件字段放置在表單內:
<form:form method="POST" action="/spring-mvc-java/uploadMultiFile" enctype="multipart/form-data">
<table>
<tr>
<td>Select a file to upload</td>
<td><input type="file" name="files" /></td>
</tr>
<tr>
<td>Select a file to upload</td>
<td><input type="file" name="files" /></td>
</tr>
<tr>
<td>Select a file to upload</td>
<td><input type="file" name="files" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
</tr>
</table>
</form:form>
我們需要確保每個輸入字段具有相同的名稱,以便將其作為 MultipartFile 的數組訪問:
@RequestMapping(value = "/uploadMultiFile", method = RequestMethod.POST)
public String submit(@RequestParam("files") MultipartFile[] files, ModelMap modelMap) {
modelMap.addAttribute("files", files);
return "fileUploadView";
}
現在,我們可以迭代這個數組以顯示文件信息:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Spring MVC File Upload</title>
</head>
<body>
<h2>Submitted Files</h2>
<table>
<c:forEach items="${files}" var="file">
<tr>
<td>OriginalFileName:</td>
<td>${file.originalFilename}</td>
</tr>
<tr>
<td>Type:</td>
<td>${file.contentType}</td>
</tr>
</c:forEach>
</table>
</body>
</html>5. 上傳文件及附加表單數據
我們還可以將附加信息同時發送到服務器,與上傳的文件一起。
我們需要在表單中包含必需的字段:
<form:form method="POST"
action="/spring-mvc-java/uploadFileWithAddtionalData"
enctype="multipart/form-data">
<table>
<tr>
<td>Name</td>
<td><input type="text" name="name" /></td>
</tr>
<tr>
<td>Email</td>
<td><input type="text" name="email" /></td>
</tr>
<tr>
<td>Select a file to upload</td>
<td><input type="file" name="file" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
</tr>
</table>
</form:form>在控制器中,我們可以使用 @RequestParam</em/> 註解獲取所有表單數據:
@PostMapping("/uploadFileWithAddtionalData")
public String submit(
@RequestParam MultipartFile file, @RequestParam String name,
@RequestParam String email, ModelMap modelMap) {
modelMap.addAttribute("name", name);
modelMap.addAttribute("email", email);
modelMap.addAttribute("file", file);
return "fileUploadView";
}類似於之前的部分,我們可以使用包含 JSTL 標籤的 HTML 頁面來顯示信息。
我們還可以將所有表單字段封裝在一個模型類中,並在控制器中使用 @ModelAttribute 註解。這在有許多額外的字段以及文件的情況下會很有幫助。
讓我們來看一下代碼:
public class FormDataWithFile {
private String name;
private String email;
private MultipartFile file;
// standard getters and setters
}@PostMapping("/uploadFileModelAttribute")
public String submit(@ModelAttribute FormDataWithFile formDataWithFile, ModelMap modelMap) {
modelMap.addAttribute("formDataWithFile", formDataWithFile);
return "fileUploadView";
}6. Spring Boot 文件上傳
如果使用 Spring Boot,我們之前所學的一切都適用。
但是,Spring Boot 讓配置和啓動一切變得更加容易,無需過多麻煩。
特別是,無需配置任何 Servlet,因為 Boot 會為我們註冊和配置它,前提是我們包含 web 模塊在我們的依賴中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>我們可以從 Maven Central 找到最新版本的 spring-boot-starter-web
如果我們想控制最大文件上傳大小,我們可以編輯我們的 application.properties:
spring.servlet.multipart.max-file-size=128KB
spring.servlet.multipart.max-request-size=128KB我們還可以控制文件上傳是否啓用以及文件上傳的位置。
spring.servlet.multipart.enabled=true
spring.servlet.multipart.location=${java.io.tmpdir}請注意,我們使用了 java.io.tmpdir 來定義上傳位置,以便我們可以在不同的操作系統中使用臨時位置。
7. 結論
在本文中,我們探討了如何在 Spring 中配置多部分支持。通過這種方法,我們可以支持我們在 Web 應用程序中上傳文件。