Пример Upload file c Spring Boot и AngularJS
1. Цель статьи
В данной статье я покажу вам как создать приложение Upload File исопльзуя Spring Boot и AngularJS, ниже является изображение для предварительного просмотра приложениея, которое вы выполним:
Оповестить на интерфейсе когда происходит ошибка загрузки:
Отобразить список загруженных файлов, и обработать скачивание когда пользователь кликает на ссылку (link).
2. Создать проект Spring Boot
На Eclipse создать проект Spring Boot:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.o7planning</groupId>
<artifactId>SpringBootFileUploadAngularJS</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringBootFileUploadAngularJS</name>
<description>Spring Boot + File Upload + AngularJS</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SpringBootFileUploadAngularJsApplication.java
package org.o7planning.sbfileupload;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootFileUploadAngularJsApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootFileUploadAngularJsApplication.class, args);
}
}
3. Form, Controller, Exception Handler
Класс UploadForm представляет данные формы HTML.
UploadForm.java
package org.o7planning.sbfileupload.form;
import org.springframework.web.multipart.MultipartFile;
public class UploadForm {
private String description;
private MultipartFile[] files;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public MultipartFile[] getFiles() {
return files;
}
public void setFiles(MultipartFile[] files) {
this.files = files;
}
}
MainController.java
package org.o7planning.sbfileupload.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("/")
public String index() {
return "upload";
}
}
Класс MainRESTController определяет REST API чтобы обрабатывать данные файла загруженного пользователем. Данный REST API будет вызван с помощью AngularJS (Смотрите в UploadFileCtrl.js).
MainRESTController.java
package org.o7planning.sbfileupload.restcontroller;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.o7planning.sbfileupload.form.UploadForm;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
public class MainRESTController {
// Linux: /home/{user}/test
// Windows: C:/Users/{user}/test
private static String UPLOAD_DIR = System.getProperty("user.home") + "/test";
@PostMapping("/rest/uploadMultiFiles")
public ResponseEntity<?> uploadFileMulti(@ModelAttribute UploadForm form) throws Exception {
System.out.println("Description:" + form.getDescription());
String result = null;
try {
result = this.saveUploadedFiles(form.getFiles());
}
// Here Catch IOException only.
// Other Exceptions catch by RestGlobalExceptionHandler class.
catch (IOException e) {
e.printStackTrace();
return new ResponseEntity<>("Error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<String>("Uploaded to: " + result, HttpStatus.OK);
}
// Save Files
private String saveUploadedFiles(MultipartFile[] files) throws IOException {
// Make sure directory exists!
File uploadDir = new File(UPLOAD_DIR);
uploadDir.mkdirs();
StringBuilder sb = new StringBuilder();
for (MultipartFile file : files) {
if (file.isEmpty()) {
continue;
}
String uploadFilePath = UPLOAD_DIR + "/" + file.getOriginalFilename();
byte[] bytes = file.getBytes();
Path path = Paths.get(uploadFilePath);
Files.write(path, bytes);
sb.append(uploadFilePath).append(", ");
}
return sb.toString();
}
@GetMapping("/rest/getAllFiles")
public List<String> getListFiles() {
File uploadDir = new File(UPLOAD_DIR);
File[] files = uploadDir.listFiles();
List<String> list = new ArrayList<String>();
for (File file : files) {
list.add(file.getName());
}
return list;
}
// @filename: abc.zip,..
@GetMapping("/rest/files/{filename:.+}")
public ResponseEntity<Resource> getFile(@PathVariable String filename) throws MalformedURLException {
File file = new File(UPLOAD_DIR + "/" + filename);
if (!file.exists()) {
throw new RuntimeException("File not found");
}
Resource resource = new UrlResource(file.toURI());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getName() + "\"")
.body(resource);
}
}
По умолчанию размер файла загруженного на Server не должен превышать 1MB. И если пользователь загружает несколько файлов одновременно, общий размер так же не должен превышать 1MB. Но вы можете конфигурировать, чтобы изменить данные параметры.
application.properties
spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=5MB
spring.thymeleaf.cache=false
RestGlobalExceptionHandler это кастомизированный класс, расширенный из класса ResponseEntityExceptionHandler. В данном классе вы можете обрабатывать исключения выброшенные (throw) из методов REST. Это поможет вам обрабатывать исключения централизованно, вместо обрабатывания исключения в каждом методе REST.
RestGlobalExceptionHandler.java
package org.o7planning.sbfileupload.exceptionhandler;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice
public class RestGlobalExceptionHandler extends ResponseEntityExceptionHandler {
// Catch max file size Exception.
@ExceptionHandler(MultipartException.class)
@ResponseBody
public ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = this.getStatus(request);
return new ResponseEntity<String>("(Message in RestGlobalExceptionHandler *): " + ex.getMessage(), status);
}
// Catch Other Exception
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseEntity<?> handleControllerRootException(HttpServletRequest request, Throwable ex) {
HttpStatus status = this.getStatus(request);
return new ResponseEntity<String>("(Message in RestGlobalExceptionHandler **): " + ex.getMessage(), status);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}
}
4. Javascript & View (Thymeleaf)
upload.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Boot File Upload with AngularJS</title>
<meta charset="utf-8" />
<!-- Check other AngularJS version at: -->
<!-- https://code.angularjs.org/1.6.9/docs/misc/downloading -->
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="/js/MainApp.js"></script>
<script src="/js/UploadFileCtrl.js"></script>
<script src="/js/GetFilesCtrl.js"></script>
</head>
<body ng-app="MainApp">
<h2>Spring Boot File Upload with AngularJS</h2>
<div ng-controller="UploadFileController">
<form>
Description: <br/>
<input type="text" name="description" ng-model="myForm.description" style="width:350px;"/>
<br/><br/>
File to upload (1): <input type="file" file-model="myForm.files[0]"/><br />
File to upload (2): <input type="file" file-model="myForm.files[1]"/><br />
File to upload (3): <input type="file" file-model="myForm.files[2]"/><br />
File to upload (4): <input type="file" file-model="myForm.files[3]"/><br />
File to upload (5): <input type="file" file-model="myForm.files[4]"/><br />
<button type="button" ng-click="doUploadFile()">Upload</button>
</form>
<h2>Upload Results:</h2>
<div style="border:1px solid #ccc;padding: 5px;">
<span ng-bind="uploadResult"></span>
</div>
</div>
<!-- Get Files -->
<hr>
<div ng-controller="GetFilesController">
<button type="button" ng-click="getAllFiles()">Get All Files</button>
<ul>
<li ng-repeat="file in allFiles">
<a href='/rest/files/{{file}}'>{{file}}</a>
</li>
</ul>
</div>
</body>
</html>
В AngularJS, использование атрибута (attribute) ng-model поможет вам с двусторонней привязкой (2-way binding) между элемент Input у Form и Model, что значит если данные на Model меняются то интерфейс (элемент Input) будет обновлен, и наоборот, если пользователь меняет на интерфейсее (элемент Input), то Model будет обновлен.
К сожалению атрибут (attribute) ng-model не поддерживает двусторонню привязку между Model и Input[file], поэтому вам нужно определить directive (директива) с названием "fileModel" чтобы построить двустороннюю привязку между Model и Input[file]. Данная Directive определена в MainApp.js:
js/MainApp.js
// main app.
var mainApp = angular.module('MainApp', []);
// DIRECTIVE - FILE MODEL
mainApp.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
Файл UploadFileCtrl.js содержит функции AngularJS управляющие загрузку файлов на Server.
js/UploadFileCtrl.js
// CONTROLLER UPLOAD FILE
mainApp.controller('UploadFileController', function($scope, $http) {
$scope.uploadResult ="";
$scope.myForm = {
description: "",
files: []
}
$scope.doUploadFile = function() {
var url = "/rest/uploadMultiFiles";
var data = new FormData();
data.append("description", $scope.myForm.description);
for (i = 0; i < $scope.myForm.files.length; i++) {
data.append("files", $scope.myForm.files[i]);
}
var config = {
transformRequest: angular.identity,
transformResponse: angular.identity,
headers: {
'Content-Type': undefined
}
}
$http.post(url, data, config).then(
// Success
function(response) {
$scope.uploadResult = response.data;
},
// Error
function(response) {
$scope.uploadResult = response.data;
});
};
});
Файл GetFilesCtrl.js содержит файл AngularJS, управляющий получение списка файлов, загруженных на Server.
js/GetFilesCtrl.js
mainApp.controller('GetFilesController', function($scope, $http) {
$scope.allFiles = [];
$scope.getAllFiles = function() {
// REST URL:
var url = "/rest/getAllFiles";
$http.get(url).then(
// Success
function(response) { alert("OK");
$scope.allFiles = response.data;
},
// Error
function(response) {
alert("Error: " + response.data);
}
);
};
});
Руководства Spring Boot
- Установите Spring Tool Suite для Eclipse
- Руководство Spring для начинающих
- Руководство Spring Boot для начинающих
- Общие свойства Spring Boot
- Руководство Spring Boot и Thymeleaf
- Руководство Spring Boot и FreeMarker
- Руководство Spring Boot и Groovy
- Руководство Spring Boot и Mustache
- Руководство Spring Boot и JSP
- Руководство Spring Boot, Apache Tiles, JSP
- Используйте Logging в Spring Boot
- Мониторинг приложений с помощью Spring Boot Actuator
- Создание веб-приложения с несколькими языками с помощью Spring Boot
- Используйте несколько ViewResolver в Spring Boot
- Используйте Twitter Bootstrap в Spring Boot
- Руководство Spring Boot Interceptor
- Руководство Spring Boot, Spring JDBC и Spring Transaction
- Руководство Spring JDBC
- Руководство Spring Boot, JPA и Spring Transaction
- Руководство Spring Boot и Spring Data JPA
- Руководство Spring Boot, Hibernate и Spring Transaction
- Интеграция Spring Boot, JPA и H2 Database
- Руководство Spring Boot и MongoDB
- Используйте несколько DataSources с Spring Boot и JPA
- Используйте несколько DataSource с Spring Boot и RoutingDataSource
- Создайте приложение для входа с Spring Boot, Spring Security, Spring JDBC
- Создайте приложение для входа с Spring Boot, Spring Security, JPA
- Создайте приложение регистрации пользователей с помощью Spring Boot, Spring Form Validation
- Пример OAuth2 Social Login в Spring Boot.
- Запускать фоновые запланированные задачи в Spring
- Пример CRUD Restful Web Service c Spring Boot
- Пример Spring Boot Restful Client c RestTemplate
- Пример CRUD с Spring Boot, REST и AngularJS
- Защита Spring Boot RESTful Service используя Basic Authentication
- Защита Spring Boot RESTful Service используя Auth0 JWT
- Пример Upload file c Spring Boot
- Пример Download file c Spring Boot
- Пример Upload file c Spring Boot и jQuery Ajax
- Пример Upload file c Spring Boot и AngularJS
- Создание веб-приложения для корзины покупок с помощью Spring Boot, Hibernate
- Руководство Spring Email
- Создайте простое приложение Chat с Spring Boot и Websocket
- Разверните приложение Spring Boot на Tomcat Server
- Развертывание приложения Spring Boot на Oracle WebLogic Server
- Установите бесплатный сертификат Let's Encrypt SSL для Spring Boot
- Настройте Spring Boot для перенаправления HTTP на HTTPS
Show More