Загрузка файлов
Этот урок освещает процесс создания серверного приложения, которое может принимать загружаемый файл.
Что вы создадите
Вы создадите Spring MVC приложение, которое принимает загружаемый файл. Вы также соберете простой клиент для загрузки тестового файла.
Что вам потребуется
- Примерно 15 минут свободного времени
- Любимый текстовый редактор или IDE
- JDK 6 и выше
- Gradle 1.11+ или Maven 3.0+
- Вы также можете импортировать код этого урока, а также просматривать web-страницы прямо из Spring Tool Suite (STS), собственно как и работать дальше из него.
Как проходить этот урок
Как и большинство уроков по Spring, вы можете начать с нуля и выполнять каждый шаг, либо пропустить базовые шаги, которые вам уже знакомы. В любом случае, вы в конечном итоге получите рабочий код.
Чтобы начать с нуля, перейдите в Настройка проекта.
Чтобы пропустить базовые шаги, выполните следующее:
- Загрузите и
распакуйте архив с кодом этого урока, либо кнонируйте из репозитория с помощью
Git:
git clone https://github.com/spring-guides/gs-uploading-files.git
- Перейдите в каталог
gs-uploading-files/initial
- Забегая вперед, создайте класс конфигурации
Когда вы закончите, можете сравнить получившийся результат с образцом в gs-uploading-files/complete
.
Настройка проекта
Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Gradle и Maven. Если вы не знакомы ни с одним из них, ознакомьтесь с соответсвующими уроками Сборка Java-проекта с использованием Gradle или Сборка Java-проекта с использованием Maven.
Создание структуры каталогов
В выбранном вами каталоге проекта создайте следующую структуру каталогов; к примеру,
командой mkdir -p src/main/java/hello
для *nix систем:
└── src └── main └── java └── hello
Создание файла сборки Gradle
Ниже представлен начальный файл сборки Gradle. Файл pom.xml находится здесь. Если вы используете Spring Tool Suite (STS), то можете импортировать урок прямо из него.
pom.xml
, вы найдете, что указана версия для maven-compiler-plugin.
В общем, это не рекомендуется делать. В данном случае он предназначен для решения проблем с нашей CI системы,
которая по умолчанию имеет старую(до Java 5) версию этого плагина.
build.gradle
buildscript {
repositories {
maven { url "http://repo.spring.io/libs-release" }
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.6.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'application'
run {
args 'sample.txt'
}
jar {
baseName = 'gs-uploading-files'
version = '0.1.0'
}
repositories {
mavenLocal()
mavenCentral()
maven { url "http://repo.spring.io/libs-release" }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("junit:junit")
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
Spring Boot gradle plugin предоставляет множество удобных возможностей:
- Он собирает все jar'ы в classpath и собирает единое, исполняемое "über-jar", что делает более удобным выполнение и доставку вашего сервиса
- Он ищет
public static void main()
метод, как признак исполняемого класса - Он предоставляет встроенное разрешение зависимостей, с определенными номерами версий для соответсвующих Spring Boot зависимостей. Вы можете переопределить на любые версии, какие захотите, но он будет по умолчанию для Boot выбранным набором версий
Создание класса конфигурации
Для загрузки файлов с использованием контейнеров Servlet 3.0, вам необходимо
зарегистрировать класс MultipartConfigElement
(который соответствует
<multipart-config>
в web.xml).
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.embedded.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.servlet.MultipartConfigElement;
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
@Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize("128KB");
factory.setMaxRequestSize("128KB");
return factory.createMultipartConfig();
}
}
Этот класс использован для настройки сервера приложений, чтобы получить загружаемый
файл, блогодаря аннотации @Configuration
.
Скоро вы добавите Spring MVC контроллер, поэтому вам необходимы обе
@EnableAutoConfiguration
и @ComponentScan
аннотации.
Обычно вы использовали @EnableWebMvc
для Spring MVC приложения, но
Spring Boot автоматически добавляет эту аннотацию, когда обнаруживает spring-webmvc
в вашем classpath. @ComponentScan
делает возможным автоматический
поиск классов с @Controller
аннотацией.
Используя @EnableAutoConfiguration
, приложение будет также обнаруживать
MultipartConfigElement
бин и делать его работоспособным для загрузки файла.
Создание контроллера загрузки файла
В Spring, REST обработкой занимаются Spring MVC контроллеры. Ниже приведенный код обеспечивает web-приложению возможность загрузки файлов.
src/main/java/hello/FileUploadController.java
package hello;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
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;
@Controller
public class FileUploadController {
@RequestMapping(value="/upload", method=RequestMethod.GET)
public @ResponseBody String provideUploadInfo() {
return "Вы можете загружать файл с использованием того же URL.";
}
@RequestMapping(value="/upload", method=RequestMethod.POST)
public @ResponseBody String handleFileUpload(@RequestParam("name") String name,
@RequestParam("file") MultipartFile file){
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name + "-uploaded")));
stream.write(bytes);
stream.close();
return "Вы удачно загрузили " + name + " в " + name + "-uploaded !";
} catch (Exception e) {
return "Вам не удалось загрузить " + name + " => " + e.getMessage();
}
} else {
return "Вам не удалось загрузить " + name + " потому что файл пустой.";
}
}
}
весь класс отмечен как @Controller
, поэтому Spring MVC
может выбрать его и просмотреть все маршруты.
Каждый метод помечен @RequestMapping
, означая путь и
REST действие. В этом случае, GET
вернут очень простое
сообщение о доступности POST
операции.
Метод handleFileUpload
предназначен для обработки
двух частей сообщения: name
и file
.
Он проверяет, что файл не пустой и, если это так, то скачивает байты.
Далее, он записывает их через BufferedOutputStream
. В итоге,
добавляет -uploaded к имени файла, чтобы показать, что файл загружен.
Создание HTML формы для загрузки файла
Создайте "index.html" файл в src/main/resources/static
(который будет
соответствовать /static
):
src/main/resources/static/index.html
<html>
<body>
<form method="POST" enctype="multipart/form-data"
action="/upload">
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>
Создание приложения исполняемым
Несмотря на то, что пакет этого сервиса может быть в составе web-приложения и
WAR файлов,
более простой подход, продемонстрированный ниже создает отдельное самостоятельное приложение.
Вы упаковываете все в единый, исполняемый JAR-файл, который запускается через хорошо знакомый
старый main()
Java-метод. Попутно, вы используете поддержку Spring для встроенного
Tomcat
контейнера сервлетов как HTTP среду выполнения вместо развертывания на сторонний экземпляр.
src/main/java/hello/Application.java
package hello;
import javax.servlet.MultipartConfigElement;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.embedded.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize("128KB");
factory.setMaxRequestSize("128KB");
return factory.createMultipartConfig();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Метод main()
передает управление вспомогательному классу
SpringApplication
, предоставляя Application.class
как аргумент его run()
методу. Это говорит Spring о том, чтобы
прочитать аннотацию метаданных из Application
и управлять им
как компонентом в Spring Application Context.
Аннотация @ComponentScan
сообщает Spring о запуске рекурсивного
поиска в пакете hello
и потомках классов, отмеченных прямо или
косвенно Spring аннотацией @Component
. При этом гарантируется,
что Spring найдет и зарегистрирует FileUploadController
,
потому что он отмечен @Controller
, что в свою очередь является
своего рода @Component
аннотацией.
@EnableAutoConfiguration
аннотация переключает на доступные по умолчанию настройки, основанные на
содержимом вашего classpath. К примеру, т.к. приложение зависит от встраиваемой
версии Tomcat(tomcat-embed-core.jar), то Tomcat сервер установлен и настроен
по умолчанию от вашего имени. И также, т.к. приложение зависит от Spring MVC
(spring-webmvc.jar), Spring MVC DispatcherServlet
настроен и зарегистрирован за вас - web.xml
не нужен! Поэтому здесь
MultipartConfigElement
, он настроен DispatcherServlet
с
функциональностью загрузки файлов. Автонастройка является мощным и гибким механизмом.
Более подробно вы можете ознакомиться в API документации.
Сборка исполняемого JAR
Вы можете собрать единый исполняемый JAR-файл, который содержит все необходимые зависимости, классы и ресурсы. Это делает его легким в загрузке, версионировании и развертывании сервиса как приложения на протяжении всего периода разработки, на различных средах и так далее.
./gradlew build
Затем вы можете запустить JAR-файл:
java -jar build/libs/gs-uploading-files-0.1.0.jar
Если вы используете Maven, вы можете запустить приложение, используя mvn spring-boot:run
,
либо вы можете собрать приложение с mvn clean package
и запустить JAR примерно так:
java -jar target/gs-uploading-files-0.1.0.jar
Запуск сервиса
Если вы используете Gradle, вы можете запустить ваш сервис из командной строки:
./gradlew clean build && java -jar build/libs/gs-uploading-files-0.1.0.jar
mvn clean package && java -jar target/gs-uploading-files-0.1.0.jar
.
Как вариант, вы можете запустить ваш сервис напрямую из Gradle примерно так:
./gradlew bootRun
mvn spring-boot:run
.Этим запускается серверная часть для получения загружаемого файла. Отладочные данные отображены. Сервис должен быть поднят и запущен через несколько секунд.
Когда сервер запустится, вам необходимо будет открыть браузер и зайти на http://localhost:8080, чтобы увидеть форму загрузки. Выберите (небольшой) файл и нажмите "Upload", вы должны увидеть страницу об успешной работе контроллера. Выбрав файл больше, вы получите некрасивую страницу об ошибке.
Вы должны в итоге увидеть следующее в окне вашего браузера:
You successfully uploaded <name of your file> into <name you types>-uploaded!
Сам контроллер ничего не печатает, но вместо этого он возвращает сообщение, размещая в окне браузера.
Итог
Поздравляем! Вы только что написали web-приложение, которое используя Spring, обрабатывает загрузку файла.
С оригинальным текстом урока вы можете ознакомиться на spring.io.
comments powered by Disqus