В этой статье показано, как загружать файлы в веб-приложение Spring Boot (структура REST) с помощью Ajax-запросов.
Инструменты, используемые в этой статье:
- Пружинный ботинок 1.4.3.ВЫПУСК
- Пружина 4.3.5. ВЫПУСК
- Вилочковый лист
- jQuery (веб-сайты)
- Знаток
- Встроенный Tomcat 8.5.6
- Браузер Google Chrome (Проверка сети)
1. Структура проекта
Стандартная структура проекта Maven.
2. Зависимость от проекта
Объявляет дополнительную зависимость jQuery
webjar для Ajax-запросов в форме HTML.
4.0.0 com.mkyong spring-boot-file-upload jar 1.0 org.springframework.boot spring-boot-starter-parent 1.4.3.RELEASE 1.8 org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-devtools true org.webjars jquery 2.2.4 org.springframework.boot spring-boot-maven-plugin
3. Загрузка файла
Для поддержки запроса и ответа Ajax самым простым решением является возврат ResponseEntity
.
3.1 Приведенный ниже пример демонстрирует три возможных способа загрузки файлов:
- Загрузка одного файла –
Составной файл
- Загрузка нескольких файлов –
Составной файл[]
- Загрузка файла карты в модель –
@ModelAttribute
package com.mkyong.controller; import com.mkyong.model.UploadModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @RestController public class RestUploadController { private final Logger logger = LoggerFactory.getLogger(RestUploadController.class); //Save the uploaded file to this folder private static String UPLOADED_FOLDER = "F://temp//"; // 3.1.1 Single file upload @PostMapping("/api/upload") // If not @RestController, uncomment this //@ResponseBody public ResponseEntity> uploadFile( @RequestParam("file") MultipartFile uploadfile) { logger.debug("Single file upload!"); if (uploadfile.isEmpty()) { return new ResponseEntity("please select a file!", HttpStatus.OK); } try { saveUploadedFiles(Arrays.asList(uploadfile)); } catch (IOException e) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } return new ResponseEntity("Successfully uploaded - " + uploadfile.getOriginalFilename(), new HttpHeaders(), HttpStatus.OK); } // 3.1.2 Multiple file upload @PostMapping("/api/upload/multi") public ResponseEntity> uploadFileMulti( @RequestParam("extraField") String extraField, @RequestParam("files") MultipartFile[] uploadfiles) { logger.debug("Multiple file upload!"); // Get file name String uploadedFileName = Arrays.stream(uploadfiles).map(x -> x.getOriginalFilename()) .filter(x -> !StringUtils.isEmpty(x)).collect(Collectors.joining(" , ")); if (StringUtils.isEmpty(uploadedFileName)) { return new ResponseEntity("please select a file!", HttpStatus.OK); } try { saveUploadedFiles(Arrays.asList(uploadfiles)); } catch (IOException e) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } return new ResponseEntity("Successfully uploaded - " + uploadedFileName, HttpStatus.OK); } // 3.1.3 maps html form to a Model @PostMapping("/api/upload/multi/model") public ResponseEntity> multiUploadFileModel(@ModelAttribute UploadModel model) { logger.debug("Multiple file upload! With UploadModel"); try { saveUploadedFiles(Arrays.asList(model.getFiles())); } catch (IOException e) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } return new ResponseEntity("Successfully uploaded!", HttpStatus.OK); } //save file private void saveUploadedFiles(Listfiles) throws IOException { for (MultipartFile file : files) { if (file.isEmpty()) { continue; //next pls } byte[] bytes = file.getBytes(); Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename()); Files.write(path, bytes); } } }
3.2 Простая модель для приведенного выше примера 3.1.3 – @ModelAttribute
package com.mkyong.model; import org.springframework.web.multipart.MultipartFile; public class UploadModel { private String extraField; private MultipartFile[] files; //getters and setters }
4. Взгляды
HTML-форма для нескольких загрузок файлов.
Spring Boot - Multiple file upload example - AJAX
Ajax Post Result
5. jQuery – Запрос Ajax
jQuery для получения формы через форму #id
и отправьте данные составной формы с помощью Ajax-запроса.
$(document).ready(function () { $("#btnSubmit").click(function (event) { //stop submit the form, we will post it manually. event.preventDefault(); fire_ajax_submit(); }); }); function fire_ajax_submit() { // Get form var form = $('#fileUploadForm')[0]; var data = new FormData(form); data.append("CustomField", "This is some extra data, testing"); $("#btnSubmit").prop("disabled", true); $.ajax({ type: "POST", enctype: 'multipart/form-data', url: "/api/upload/multi", data: data, //http://api.jquery.com/jQuery.ajax/ //https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects processData: false, //prevent jQuery from automatically transforming the data into a query string contentType: false, cache: false, timeout: 600000, success: function (data) { $("#result").text(data); console.log("SUCCESS : ", data); $("#btnSubmit").prop("disabled", false); }, error: function (e) { $("#result").text(e.responseText); console.log("ERROR : ", e); $("#btnSubmit").prop("disabled", false); } }); }
6. Обработчик исключений
Чтобы обработать исключение из Ajax-запроса, просто расширьте ResponseEntityExceptionHandler
и вернуть обратно Отзывчивость
.
package com.mkyong.exception; 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; //http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling @ControllerAdvice public class RestGlobalExceptionHandler extends ResponseEntityExceptionHandler { // Catch file size exceeded exception! @ExceptionHandler(MultipartException.class) @ResponseBody ResponseEntity> handleControllerException(HttpServletRequest request, Throwable ex) { HttpStatus status = getStatus(request); return new ResponseEntity(ex.getMessage(), status); // example //return new ResponseEntity("success", responseHeaders, HttpStatus.OK); } 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); } }
7. ДЕМОНСТРАЦИЯ
Запустите Spring Boot с помощью встроенного по умолчанию Tomcat mvn spring-boot:выполнить
.
7.1 Доступ http://localhost:8080/ , выберите несколько файлов и нажмите кнопку отправить, чтобы запустить ajax-запрос.
7.2 Google Chrome, просмотрите запрос и ответ в разделе “Проверка сети”
7.3 Google Chrome, “Запрашивать полезную нагрузку”
8. локон Тестирование
Дополнительное тестирование с помощью команды cURL
.
8.1 Тестовая загрузка одного файла.
$ curl -F file=@"f:\\data.txt" http://localhost:8080/api/upload/ Successfully uploaded - data.txt
8.2 Протестируйте загрузку нескольких файлов.
$ curl -F extraField="abc" -F files=@"f://data.txt" -F files=@"f://data2.txt" http://localhost:8080/api/upload/multi/ Successfully uploaded - data.txt , data2.txt
8.3 Проверка загрузки нескольких файлов, сопоставление с моделью.
$ curl -F extraField="abc" -F files=@"f://data.txt" -F files=@"f://data2.txt" http://localhost:8080/api/upload/multi/model Successfully uploaded!
8.4 Протестируйте большой видеофайл (100 МБ), появится следующее сообщение об ошибке.
$ curl -F file=@"F://movies//300//Sample.mkv" http://localhost:8080/api/upload/ Attachment size exceeds the allowable limit! (10MB)
9. Завиток Тестирование + Пользовательский объект ошибки
9.1 Создайте объект для хранения сведений об ошибке.
package com.mkyong.exception; public class CustomError { String errCode; String errDesc; public CustomError(String errCode, String errDesc) { this.errCode = errCode; this.errDesc = errDesc; } //getters and setters }
9.2 Обновите глобальный обработчик исключений для поддержки Пользовательская ошибка
объект.
package com.mkyong.exception; 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 { @ExceptionHandler(MultipartException.class) @ResponseBody ResponseEntity> handleControllerException(HttpServletRequest request, Throwable ex) { HttpStatus status = getStatus(request); return new ResponseEntity(new CustomError("0x000123", "Attachment size exceeds the allowable limit! (10MB)"), status); //return new ResponseEntity("Attachment size exceeds the allowable limit! (10MB)", 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); } }
9.3 Сверните, чтобы снова загрузить большой файл.
$ curl -F file=@"F://movies//300//Sample.mkv" http://localhost:8080/api/upload/ {"errCode":"0x000123","errDesc":"Attachment size exceeds the allowable limit! (10MB)"}
Сделано. Обратная связь приветствуется.
10. Скачать Исходный Код
Рекомендации
- Обработка ошибок при весенней загрузке
- Пример загрузки файла весенней загрузки
- Пример загрузки файла Spring MVC
- Пример весеннего ботинка Hello World – Thymeleaf
- Википедия – Завиток
- jQuery.аякс()
- MDN – Использование объектов FormData
Оригинал: “https://mkyong.com/spring-boot/spring-boot-file-upload-example-ajax-and-rest/”