Пример учебника по загрузке файлов Spring MVC – одиночные и множественные файлы

Загрузка файлов – очень распространенная задача в любом веб-приложении. Мы уже видели, как загружать файлы в Servlet и загружать файлы в Struts2. Сегодня мы узнаем о загрузке файлов в Spring, в частности о загрузке файлов в Spring MVC для одного и нескольких файлов.

Загрузка файлов в Spring MVC

Фреймворк Spring MVC предоставляет поддержку для загрузки файлов путем интеграции с API Apache Commons FileUpload. Процесс загрузки файлов очень прост и требует простых настроек. Мы создадим простой проект Spring MVC в STS, который будет выглядеть примерно как на изображении ниже. Большая часть кода состоит из шаблонного кода, сгенерированного средством STS, мы сосредоточимся на изменениях, необходимых для использования интеграции загрузки файлов Spring.

Зависимости Maven для Apache Commons FileUpload

Прежде всего, нам нужно добавить зависимости Apache Commons FileUpload в наш файл pom.xml, чтобы необходимые jar-файлы стали частью веб-приложения. Ниже приведен фрагмент зависимости из моего файла pom.xml.

<!-- Apache Commons FileUpload --> 
<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.3.1</version>
</dependency>

<!-- Apache Commons IO --> 
<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.4</version>
</dependency>

Представления формы загрузки файла Spring

Мы создадим две JSP-страницы для разрешения загрузки одного и нескольких файлов в веб-приложении Spring. Код представления upload.jsp:

<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Upload File Request Page</title>
</head>
<body>
	<form method="POST" action="uploadFile" enctype="multipart/form-data">
		File to upload: <input type="file" name="file"><br /> 
		Name: <input type="text" name="name"><br /> <br /> 
		<input type="submit" value="Upload"> Press here to upload the file!
	</form>	
</body>
</html>

Код представления uploadMultiple.jsp:

<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Upload Multiple File Request Page</title>
</head>
<body>
	<form method="POST" action="uploadMultipleFile" enctype="multipart/form-data">
		File1 to upload: <input type="file" name="file"><br /> 
		Name1: <input type="text" name="name"><br /> <br /> 
		File2 to upload: <input type="file" name="file"><br /> 
		Name2: <input type="text" name="name"><br /> <br />
		<input type="submit" value="Upload"> Press here to upload the file!
	</form>
</body>
</html>

Обратите внимание, что эти файлы являются простыми HTML-файлами, я не использую никакие теги JSP или Spring для избежания сложности. Важный момент: атрибут enctype формы должен быть multipart/form-data, чтобы веб-приложение Spring знало, что запрос содержит данные файла, которые нужно обработать. Также обратите внимание, что для нескольких файлов поля формы “file” и “name” совпадают в полях ввода, чтобы данные были отправлены в виде массива. Мы возьмем входной массив, разберем данные файла и сохраним их с указанным именем файла.

Настройка многокомпонентной конфигурации Spring MVC

Для использования Apache Commons FileUpload для обработки многокомпонентных запросов нам просто нужно настроить бин multipartResolver с классом org.springframework.web.multipart.commons.CommonsMultipartResolver. Наш конечный файл конфигурации Spring выглядит следующим образом. Код servlet-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing 
		infrastructure -->

	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving 
		up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/**" location="/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources 
		in the /WEB-INF/views directory -->
	<beans:bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>

	<beans:bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

		 <!-- setting maximum upload size -->
		<beans:property name="maxUploadSize" value="100000" />

	</beans:bean>

	<context:component-scan base-package="com.journaldev.spring.controller" />

</beans:beans>

Обратите внимание, что я устанавливаю максимальный размер загружаемого файла, предоставляя значение свойства maxUploadSize для бина multipartResolver. Если вы посмотрите в исходный код класса DispatcherServlet, вы увидите, что переменная MultipartResolver с именем multipartResolver определена и инициализирована в следующем методе.

private void initMultipartResolver(ApplicationContext context)
  {
    try
    {
      this.multipartResolver = ((MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class));
      if (this.logger.isDebugEnabled()) {
        this.logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
      }
    }
    catch (NoSuchBeanDefinitionException ex)
    {
      this.multipartResolver = null;
      if (this.logger.isDebugEnabled())
        this.logger.debug("Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided");
    }
  }

С этой конфигурацией любой запрос с enctype как multipart/form-data будет обрабатываться multipartResolver перед передачей в класс контроллера.

Класс контроллера загрузки файла Spring

Класс контроллера очень простой, нам нужно определить методы обработчика для URI uploadFile и uploadMultipleFile. Код FileUploadController.java:

package com.journaldev.spring.controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

/**
 * Handles requests for the application file upload requests
 */
@Controller
public class FileUploadController {

	private static final Logger logger = LoggerFactory
			.getLogger(FileUploadController.class);

	/**
	 * Upload single file using Spring Controller
	 */
	@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
	public @ResponseBody
	String uploadFileHandler(@RequestParam("name") String name,
			@RequestParam("file") MultipartFile file) {

		if (!file.isEmpty()) {
			try {
				byte[] bytes = file.getBytes();

				// Создание каталога для хранения файла
				String rootPath = System.getProperty("catalina.home");
				File dir = new File(rootPath + File.separator + "tmpFiles");
				if (!dir.exists())
					dir.mkdirs();

				// Создание файла на сервере
				File serverFile = new File(dir.getAbsolutePath()
						+ File.separator + name);
				BufferedOutputStream stream = new BufferedOutputStream(
						new FileOutputStream(serverFile));
				stream.write(bytes);
				stream.close();

				logger.info("Server File Location="
						+ serverFile.getAbsolutePath());

				return "You successfully uploaded file=" + name;
			} catch (Exception e) {
				return "You failed to upload " + name + " => " + e.getMessage();
			}
		} else {
			return "You failed to upload " + name
					+ " because the file was empty.";
		}
	}

	/**
	 * Upload multiple file using Spring Controller
	 */
	@RequestMapping(value = "/uploadMultipleFile", method = RequestMethod.POST)
	public @ResponseBody
	String uploadMultipleFileHandler(@RequestParam("name") String[] names,
			@RequestParam("file") MultipartFile[] files) {

		if (files.length != names.length)
			return "Mandatory information missing";

		String message = "";
		for (int i = 0; i < files.length; i++) {
			MultipartFile file = files[i];
			String name = names[i];
			try {
				byte[] bytes = file.getBytes();

				// Создание каталога для хранения файла
				String rootPath = System.getProperty("catalina.home");
				File dir = new File(rootPath + File.separator + "tmpFiles");
				if (!dir.exists())
					dir.mkdirs();

				// Создание файла на сервере
				File serverFile = new File(dir.getAbsolutePath()
						+ File.separator + name);
				BufferedOutputStream stream = new BufferedOutputStream(
						new FileOutputStream(serverFile));
				stream.write(bytes);
				stream.close();

				logger.info("Server File Location="
						+ serverFile.getAbsolutePath());

				message = message + "You successfully uploaded file=" + name
						+ "
"; } catch (Exception e) { return "You failed to upload " + name + " => " + e.getMessage(); } } return message; } }

Обратите внимание на использование аннотаций Spring, которые упрощают нашу жизнь и делают код более читабельным. Метод uploadFileHandler используется для обработки сценария загрузки одного файла, тогда как метод uploadMultipleFileHandler используется для обработки сценария загрузки нескольких файлов. Фактически, мы могли бы использовать один метод для обработки обоих сценариев. Теперь экспортируйте приложение как файл WAR и разверните его в контейнере сервлетов Tomcat. При запуске нашего приложения ниже приведены изображения запросов и ответов.

Пример загрузки файла в Spring MVC

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

Загрузите проект Spring File Upload

Source:
https://www.digitalocean.com/community/tutorials/spring-mvc-file-upload-example-single-multiple-files