Перейти к основному содержимому

Загрузка файла с помощью Spring MVC

· 6 мин. чтения

1. Обзор

В предыдущих руководствах мы представили основы обработки форм и изучили библиотеку тегов форм в Spring MVC.

В этом руководстве мы сосредоточимся на том, что предлагает Spring для многокомпонентной поддержки (загрузки файлов) в веб-приложениях.

Spring позволяет нам включить эту поддержку составных частей с помощью подключаемых объектов MultipartResolver . Платформа предоставляет одну реализацию MultipartResolver для использования с Commons FileUpload и другую для использования с анализом составных запросов Servlet 3.0 .

После настройки MultipartResolver мы увидим, как загрузить один файл и несколько файлов.

Мы также коснемся Spring Boot.

2. Загрузить файл Commons

Чтобы использовать CommonsMultipartResolver для обработки загрузки файла, нам нужно добавить следующую зависимость:

<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>

Теперь мы можем определить bean- компонент CommonsMultipartResolver в нашей конфигурации Spring.

Этот MultipartResolver поставляется с рядом методов set для определения таких свойств, как максимальный размер для загрузки:

@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return multipartResolver;
}

Здесь нам нужно управлять различными свойствами CommonsMultipartResolver в самом определении Бина.

3. С сервлетом 3.0

Чтобы использовать многокомпонентный синтаксический анализ Servlet 3.0 , нам нужно настроить пару частей приложения.

Во-первых, нам нужно установить MultipartConfigElement в нашей регистрации DispatcherServlet `` :

public class MainWebAppInitializer implements WebApplicationInitializer {

private String TMP_FOLDER = "/tmp";
private 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 * 2, MAX_UPLOAD_SIZE / 2);

appServlet.setMultipartConfig(multipartConfigElement);
}
}

В объекте MultipartConfigElement мы настроили место хранения, максимальный размер отдельного файла, максимальный размер запроса (в случае нескольких файлов в одном запросе) и размер, при котором ход загрузки файла сбрасывается в место хранения.

Эти настройки должны применяться на уровне регистрации сервлета, потому что Servlet 3.0 не позволяет их регистрировать в MultipartResolver , как в случае с CommonsMultipartResolver .

Как только это будет сделано, мы можем добавить StandardServletMultipartResolver в нашу конфигурацию Spring :

@Bean
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}

4. Загрузка файла ** **

Чтобы загрузить наш файл, мы можем создать простую форму, в которой мы используем тег ввода HTML с type='file' .

Независимо от выбранной нами конфигурации обработки загрузки, нам необходимо установить для атрибута кодирования формы значение multipart/form-data .

Это позволяет браузеру узнать, как кодировать форму:

<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>

5. Загрузка нескольких файлов

Чтобы загрузить несколько файлов в одном запросе, мы просто помещаем в форму несколько полей ввода файла:

<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>

6. Загрузка файлов с дополнительными данными формы

Мы также можем отправить дополнительную информацию на сервер вместе с загружаемым файлом.

Нам просто нужно включить необходимые поля в форму:

<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 :

@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";
}

Как и в предыдущих разделах, мы можем использовать HTML-страницу с тегами JSTL для отображения информации.

Мы также можем инкапсулировать все поля формы в класс модели и использовать аннотацию @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";
}

7. Загрузка загрузочного файла Spring

Если мы используем Spring Boot, все, что мы видели до сих пор, остается в силе.

Тем не менее, Spring Boot упрощает настройку и запускает все без особых хлопот.

В частности, нет необходимости настраивать какой-либо сервлет , так как Boot зарегистрирует и настроит его за нас, при условии, что мы включим веб-модуль в наши зависимости:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.1</version>
</dependency>

Мы можем найти последнюю версию spring-boot-starter-web на Maven Central.

Если мы хотим контролировать максимальный размер загружаемого файла, мы можем отредактировать наш 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} для определения местоположения загрузки, чтобы мы могли использовать временное местоположение для разных операционных систем.

8. Заключение

В этой статье мы рассмотрели различные способы настройки поддержки составных частей в Spring. Используя их, мы можем поддерживать загрузку файлов в наших веб-приложениях.

Реализацию этого туториала можно найти в проекте GitHub . Когда проект выполняется локально, пример формы доступен по адресу http://localhost:8080/spring-mvc-java/fileUpload.