Spring Boot REST Uploadhttps://www.springboot.ch/setfailed?&atomFri, 29 Mar 2024 11:26:46 +0000stack.ch
https://stack.ch/
3a0bbb9b-edbf-11ee-8c11-005056bb85fbSimtech AG - Blog - Spring Boot Blogs - Spring Boot REST Upload
https://www.springboot.ch/setfailed
3a0bbcb3-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000Spring Boot REST Upload
https://www.springboot.ch/setfailed
3a0bbe39-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000
https://www.springboot.ch/setfailed
3a0bbf45-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000Der Upload von Dateien ist eine Grundanforderung von Web Anwendungen und damit auch von REST Services. Dieser Blog zeigt auf, wie man MultipartFile Daten mit REST Services programmiert und testet. Wir arbeiten mit der Eclipse IDE und den Spring Tools 4.
https://www.springboot.ch/setfailed
3a0bc0b9-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000Zuerst öffnen wir die Eclipse IDE und erstellen mit dem Spring Tools 4 Plugin eine Spring Boot Application von Grund auf: Mit dem Abschluss des Projekts erhalten Sie eine lauffähige leere Spring Boot Application.
https://www.springboot.ch/setfailed
3a0bcdd5-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000Um Dateien als Upload einem Spring REST Service zur Verfügung zu stellen, verwenden wir eine Instanz der Spring Klasse org.springframework.web.multipart.MultipartFile. Es handelt sich hier um eine InputStreamSource Klasse, welche ein File als Multipart Request repräsentiert. Das folgende Listing zeigt den UploadController mit der Methode uploadDokument und einem MultipartFile Parameter:package ch.std.rest.upload.controller;
import java.nio.file.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import ch.std.rest.upload.dto.RequestUploadDTO;
import ch.std.rest.upload.dto.ResponseUploadDTO;
import ch.std.rest.upload.service.FileService;
@RestController
@RequestMapping(path="/rest")
public class UploadController {
Logger logger = LoggerFactory.getLogger(UploadController.class);
private FileService fileService;
public UploadController(FileService fileService) {
this.fileService = fileService;
}
@PostMapping(path = "upload", produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseUploadDTO uploadDokument(@RequestPart("file") MultipartFile file) {
String fileName = file.getOriginalFilename();
ResponseUploadDTO responseUploadDTO = new ResponseUploadDTO();
try {
Path out = this.fileService.save(fileName, file.getInputStream());
responseUploadDTO.setSuccess("file uploaded");
responseUploadDTO.setPath(out);
} catch (Exception e) {
responseUploadDTO.setFailed(e.getMessage());
}
return responseUploadDTO;
}
}
Das Listing verwendet als Response die Klasse ResponseUploadDTO:package ch.std.rest.upload.dto;
import java.nio.file.Path;
public class ResponseUploadDTO {
private int status;
private String message;
private Path path;
public void setSuccess(String message) {
this.status = 0;
this.message = message;
}
public void setFailed(String message) {
this.status = 1;
this.message = message;
}
public String getMessage() {
return message;
}
public Path getPath() {
return path;
}
public void setPath(Path path) {
this.path = path;
}
public int getStatus() {
return status;
}
@Override
public String toString() {
return "ResponseUploadDTO [status=" + status + ", message=" + message + ", path=" + path + "]";
}
}Die Verarbeitung des Uploads erfolgt über den FileService:package ch.std.rest.upload.service;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class FileService {
Logger logger = LoggerFactory.getLogger(FileService.class);
@Value("${upload.service.path}")
private String rootPath;
public FileService() {
}
public Path save(String fileName, InputStream is) throws IOException {
byte[] buffer = new byte[1 << 20];
int bytesRead = -1;
int bytesWritten = 0;
Path out = Path.of(rootPath, fileName);
try (OutputStream os = Files.newOutputStream(out)) {
while((bytesRead = is.read(buffer)) > 0) {
os.write(buffer, 0, bytesRead);
bytesWritten += bytesRead;
}
}
logger.info("file " + fileName + " written to path " + out + ", bytes written " + bytesWritten);
return out;
}
}Der File Service speichert die uploaded Datei relativ zum Pfad definiert durch das Property "upload.service.path". Solches definieren wir in der application.properteies Datei:upload.service.path=/tmp
https://www.springboot.ch/setfailed
3a0bd9ba-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000Das folgende Listing zeigt den Integration Test für den UploadController upload REST Endpoint:package ch.std.demo.upload.rest.test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.util.LinkedMultiValueMap;
import ch.std.demo.upload.dto.RequestUploadDTO;
import ch.std.demo.upload.dto.ResponseUploadDTO;
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class UploadServiceIntegrationTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void contextLoads() {
}
@Test
public void testUploadController() throws Exception {
var multipart = new LinkedMultiValueMap<>();
multipart.add("file", new org.springframework.core.io.ClassPathResource("dummy.pdf"));
final ResponseEntity<ResponseUploadDTO> post = this.restTemplate.postForEntity("/rest/upload",
new HttpEntity<>(multipart, headers()), ResponseUploadDTO.class);
assertEquals(HttpStatus.OK, post.getStatusCode());
System.out.println("response = " + post.getBody());
}
private HttpHeaders headers() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
return headers;
}
}Der Integration Test verwendet die Datei dummy.pdf, welche im Pfad "src/test/resources" abgelegt ist. Die Datei dummy.pdf können Sie via Hyperlink downloaden und in das Projekt integrieren. Der Integration Unit Test sollte korrekt funktionieren.
https://www.springboot.ch/setfailed
3a0be128-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000Das folgende Listing zeigt einen REST Endpoint mit zusätzlichem Request DTO Objekt:@PostMapping(path = "uploaddto", produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseUploadDTO uploadDokumentWithDTO(@RequestPart("dto") RequestUploadDTO dto, @RequestPart("file") MultipartFile file) {
String fileName = dto.getFileName();
ResponseUploadDTO responseUploadDTO = new ResponseUploadDTO();
try {
Path out = this.fileService.save(fileName, file.getInputStream());
responseUploadDTO.setSuccess("file uploaded");
responseUploadDTO.setPath(out);
} catch (Exception e) {
responseUploadDTO.setFailed(e.getMessage());
}
return responseUploadDTO;
}Den zugehörigen Integration Test sehen Sie im folgenden Listing:@Test
public void testUploadDTOController() throws Exception {
var multipart = new LinkedMultiValueMap<>();
RequestUploadDTO requestUploadDTO = new RequestUploadDTO();
requestUploadDTO.setFileName("dummydto.pdf");
multipart.add("dto", requestUploadDTO);
multipart.add("file", new org.springframework.core.io.ClassPathResource("dummy.pdf"));
final ResponseEntity<ResponseUploadDTO> post = this.restTemplate.postForEntity("/rest/uploaddto",
new HttpEntity<>(multipart, headers()), ResponseUploadDTO.class);
assertEquals(HttpStatus.OK, post.getStatusCode());
System.out.println("response = " + post.getBody());
}Die RequestDTO Klasse finden Sie hier:package ch.std.rest.upload.dto;
public class RequestUploadDTO {
private String fileName;
public RequestUploadDTO() {
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}Der Test sollte korrekt funktionieren.
https://www.springboot.ch/setfailed
3a0be6b8-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000Das gesamte Beispiel finden Sie unter dem Link springbootrestupload.zip.
https://www.springboot.ch/setfailed
3a0beaf5-edbf-11ee-8c11-005056bb85fbFri, 29 Mar 2024 11:26:46 +0000War dieser Blog für Sie wertvoll. Wir danken für jede Anregung und FeedbackÜber uns
https://www.springboot.ch/about
Fri, 29 Mar 2024 11:26:46 +00003a0bee38-edbf-11ee-8c11-005056bb85fbAktuell
https://www.springboot.ch/
Fri, 29 Mar 2024 11:26:46 +00003a0beee5-edbf-11ee-8c11-005056bb85fbAGB
https://www.springboot.ch/agb
Fri, 29 Mar 2024 11:26:46 +00003a0bef9d-edbf-11ee-8c11-005056bb85fbBildungswege
https://www.springboot.ch/bildungswege
Fri, 29 Mar 2024 11:26:46 +00003a0bf042-edbf-11ee-8c11-005056bb85fbBlog
https://www.springboot.ch/blog
Fri, 29 Mar 2024 11:26:46 +00003a0bf0e2-edbf-11ee-8c11-005056bb85fbRufen Sie mich an
https://www.springboot.ch/callus
Fri, 29 Mar 2024 11:26:46 +00003a0bf190-edbf-11ee-8c11-005056bb85fbCharts
https://www.springboot.ch/charts
Fri, 29 Mar 2024 11:26:46 +00003a0bf229-edbf-11ee-8c11-005056bb85fbConsulting
https://www.springboot.ch/consulting
Fri, 29 Mar 2024 11:26:46 +00003a0bf2c7-edbf-11ee-8c11-005056bb85fbKontakt
https://www.springboot.ch/contact
Fri, 29 Mar 2024 11:26:46 +00003a0bf364-edbf-11ee-8c11-005056bb85fbAusbildung/Kurse
https://www.springboot.ch/education
Fri, 29 Mar 2024 11:26:46 +00003a0bf41e-edbf-11ee-8c11-005056bb85fbSoftware Engineering
https://www.springboot.ch/engineering
Fri, 29 Mar 2024 11:26:46 +00003a0bf4b8-edbf-11ee-8c11-005056bb85fbFreelancer
https://www.springboot.ch/freelancer
Fri, 29 Mar 2024 11:26:46 +00003a0bf557-edbf-11ee-8c11-005056bb85fbImpressum
https://www.springboot.ch/impressum
Fri, 29 Mar 2024 11:26:46 +00003a0bf603-edbf-11ee-8c11-005056bb85fbKursleiter
https://www.springboot.ch/kursleiter
Fri, 29 Mar 2024 11:26:46 +00003a0bf69f-edbf-11ee-8c11-005056bb85fbNetzwerk
https://www.springboot.ch/network
Fri, 29 Mar 2024 11:26:46 +00003a0bf747-edbf-11ee-8c11-005056bb85fbReferenzen
https://www.springboot.ch/references
Fri, 29 Mar 2024 11:26:46 +00003a0bf7e5-edbf-11ee-8c11-005056bb85fbSitemap
https://www.springboot.ch/sitemap
Fri, 29 Mar 2024 11:26:46 +00003a0bf918-edbf-11ee-8c11-005056bb85fbTools
https://www.springboot.ch/tools
Fri, 29 Mar 2024 11:26:46 +00003a0bf9b7-edbf-11ee-8c11-005056bb85fbVision
https://www.springboot.ch/vision
Fri, 29 Mar 2024 11:26:46 +00003a0bfa65-edbf-11ee-8c11-005056bb85fb