Beispiel für das Hochladen von Spring Boot-Dateien - Ajax und REST
Dieser Artikel zeigt Ihnen, wie Sie Dateien in einer Spring Boot-Webanwendung (REST-Struktur) mithilfe von Ajax-Anforderungen hochladen.
In diesem Artikel verwendete Tools:
-
Spring Boot 1.4.3.RELEASE
-
Feder 4.3.5.FREIGABE
-
Thymeleaf
-
jQuery (Webjars)
-
Maven
-
Embedded Tomcat 8.5.6
-
Google Chrome Browser (Network Inspect)
1. Projektstruktur
Eine Standard-Maven-Projektstruktur.

2. Projektabhängigkeit
Deklariert eine zusätzliche Webjar-Abhängigkeit vonjQueryfür Ajax-Anforderungen in HTML-Form.
pom.xml
4.0.0 com.example 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. Datei-Upload
Zur Unterstützung der Ajax-Anforderung und -Antwort wird die einfachste Lösung inResponseEntity zurückgegeben.
3.1 The below example demonstrates three possible ways to upload files:
-
Upload einzelner Dateien -
MultipartFile -
Upload mehrerer Dateien -
MultipartFile[] -
Kartendatei in ein Modell hochladen -
@ModelAttribute
RestUploadController.java
package com.example.controller;
import com.example.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(List files) 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 A simple model for above example 3.1.3 – @ModelAttribute
UploadModel.java
package com.example.model;
import org.springframework.web.multipart.MultipartFile;
public class UploadModel {
private String extraField;
private MultipartFile[] files;
//getters and setters
}
4. Die Ansichten
HTML-Formular für mehrere Datei-Uploads.
upload.html
Spring Boot - Multiple file upload example - AJAX
Ajax Post Result
5. jQuery - Ajax-Anfrage
jQuery, um das Formular über das Formular#id abzurufen und die mehrteiligen Formulardaten per Ajax-Anforderung zu senden.
resources/static/js/main.js
$(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. Ausnahmehandler
Um eine Ausnahme von der Ajax-Anforderung zu behandeln, erweitern Sie einfachResponseEntityExceptionHandler und geben SieResponseEntity zurück.
RestGlobalExceptionHandler.java
package com.example.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. DEMO
Starten Sie Spring Boot mit den standardmäßig eingebetteten Tomcatmvn spring-boot:run.
7.1 Access http://localhost:8080/, select few files and clicks submit to fire the ajax request.

7.2 Google Chrome, review the request and response in the “Network Inspect”

7.3 Google Chrome, “Request Payload”

8. cURL-Test
Weitere Tests mit dem BefehlcURL.
8.1 Test single file upload.
Terminal
$ curl -F file=@"f:\\data.txt" http://localhost:8080/api/upload/ Successfully uploaded - data.txt
8.2 Test multiple file upload.
Terminal
$ 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 Test multiple file upload, maps to Model.
Terminal
$ 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 Test a large movie file (100MB), the following error message will be displayed.
Terminal
$ curl -F file=@"F://movies//300//Sample.mkv" http://localhost:8080/api/upload/ Attachment size exceeds the allowable limit! (10MB)
9. cURL-Test + Benutzerdefiniertes Fehlerobjekt
9.1 Create an object to store the error detail.
CustomError.java
package com.example.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 Update the global exception handler to support CustomError object.
RestGlobalExceptionHandler.java
package com.example.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 to upload a large file again.
Terminal
$ curl -F file=@"F://movies//300//Sample.mkv" http://localhost:8080/api/upload/
{"errCode":"0x000123","errDesc":"Attachment size exceeds the allowable limit! (10MB)"}
Erledigt. Feedback ist willkommen.
10. Quellcode herunterladen
Herunterladen -spring-boot-file-upload-ajax-rest.zip (11 KB)