Często tworząc aplikacje, potrzebujemy dać możliwość użytkownikom przesyłania plików na serwer (upload). Mogą to być przykładowo zdjęcia przesłane przez użytkowników. W tym wpisie pokażę, jak można to łatwo zrobić.
Wpis jest częścią serii wpisów na temat Spring Boot. Zapraszam do zapoznania się z pozostałymi wpisami na blogu!
- Spring Boot – szybkie tworzenie aplikacji web w Javie
- Spring Boot – Interakcja z bazą danych czyli Spring Data JPA
- Spring Boot – Widoki
- Użycie Spring Security w Spring Boot
- Spring Boot Web – Przekazywanie zmiennych do aplikacji przez URL czyli użycie @RequestParam i @PathVariable
- Spring Boot Test – testowanie aplikacji w Spring Boocie
- Wsparcie dla pola typu JSONB w PostgreSQL dla Spring Data JPA + Hibernate
- Wysyłanie plików na serwer przez Spring Boot
- Spring Boot – Spring Data JPA część II: Powiązania między tabelami
- Spring Mail + Spring Boot – łatwe wysyłanie maili z aplikacji w Javie
- Docker + Spring Boot – zamykamy aplikację w kontenerze Dockerowym
- Java Bean Validation + Spring Boot – sprawdzanie poprawności danych w Spring Boocie
- Spring Boot + Swagger UI
- Serwer Amazon EC2 i SSL od Let’s encrypt w aplikacji Spring Boot
Zakładam, że wiesz już jak stworzyć podstawową aplikację w Spring Boocie, więc pomijam etap dodawania zależności i tworzenia głównej klasy. Jeśli chcesz się tego nauczyć, możesz przeczytać o tym w poprzednim wpisie: Spring Boot – Szybkie tworzenie aplikacji web w Javie.
Przykładowy kod możecie znaleźć w GitHubie pod adresem: https://github.com/mloza/spring-boot-file-upload
Formularz HTML do wysyłania plików
Na początek będziemy potrzebowali formularza HTML, w którym damy użytkownikowi możliwość wybrania pliku. Tworzymy plik index.html w resources/static i tworzymy w nim formularz.
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" | |
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>File upload</title> | |
</head> | |
<body> | |
<form action="/upload" method="post" enctype="multipart/form-data"> | |
<input type="file" name="fileupload"/> | |
<button type="submit">WyÅlij</button> | |
</form> | |
</body> | |
</html> |
Ważne, aby w elemencie form ustawić method=”post” oraz enctype=”multipart/form-data”. Bez tych atrybutów, upload nie zadziała. Action ustawiłem na /upload, pod ten endpoint zostanie przesłany nasz plik.
Po uruchomieniu aplikacji i wejściu na stronę http://localhost:8080 powinniśmy ujrzeć nasz formularz, będzie on wyglądał mniej więcej tak:
Obsługa wysyłania po stronie serwera
Mając już formularz, musimy obsłużyć odbieranie pliku po stronie serwera. Potrzebujemy controller, który będzie obsługiwał endpoint /upload:
@Controller | |
public class UploadController { | |
@PostMapping("/upload") | |
@ResponseBody // 1 | |
public String handleFile(@RequestPart(name = "fileupload") MultipartFile file) { // 2 | |
File uploadDirectory = new File("uploads"); | |
uploadDirectory.mkdirs(); // 3 | |
File oFile = new File("uploads/" + file.getOriginalFilename()); | |
try (OutputStream os = new FileOutputStream(oFile); | |
InputStream inputStream = file.getInputStream()) { | |
IOUtils.copy(inputStream, os); // 4 | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return "WystÄ piÅ bÅÄ d podczas przesyÅania pliku: " + e.getMessage(); | |
} | |
return "ok!"; | |
return "ok!"; | |
} | |
} |
To cały kod potrzebny do odebrania pliku i zapisania go na serwerze. W miejscu oznaczonym jako // 1 mówimy, że zwrócimy z metody odpowiedź, normalnie Spring szukałby widoku o nazwie, którą zwracamy. Następnie jako parametr metody przyjmujemy MultipartFile (// 2) o nazwie fileupload (nazwa ta musi być taka sama jak nazwa pola w formularzu. W miejscu // 3 upewniam się, że katalog, do którego chcę zapisać plik, istnieje, a jeśli nie, to go tworzę. Ostatnie co nam pozostało, to stworzyć strumień wyjściowy, pobrać strumień wejściowy z przesłanego pliku i przekopiować zawartość jednego do drugiego (//4). I to wszystko.
Jeżeli uruchomimy teraz aplikację, wybierzemy plik przez formularz i klikniemy przycisk wyślij, powinien się on pojawić w katalogu uploads w głównym katalogu aplikacji. W przeglądarce powinniśmy otrzymać napis „ok!”.
Wyświetlanie wysłanych plików
Mamy już wysyłanie na serwer, teraz chcielibyśmy pobrać te pliki. Załóżmy, że obsługiwaliśmy wysyłanie obrazków. Aby je wyświetlić, musimy ustawić odpowiednio nagłówek content-type i zwrócić zawartość obrazka jako body. Umożliwi nam to poniższy kod.
@GetMapping("image/{name}") | |
public ResponseEntity showImage(@PathVariable String name) throws IOException { | |
File file = new File("uploads/" + name); | |
if (!file.exists()) { | |
return ResponseEntity.notFound().build(); | |
} | |
return ResponseEntity.ok() | |
.contentType(MediaType.valueOf(URLConnection.guessContentTypeFromName(name))) | |
.body(Files.readAllBytes(file.toPath())); | |
} |
Po wejściu pod adres http://localhost:8080/image/nazwa-obrazka.jpg zostanie wyświetlony wysłany wcześniej obraz. Aby zwrócić odpowiedni content-type, jest on tworzony (jak nazwa metody mówi, zgadywany) na podstawie nazwy pliku.
Podsumowanie
Prosty upload plików możemy stworzyć bardzo szybko przy pomocy niewielkiej ilości kodu. Jednak przed zapisaniem pliku na dysku należałoby go zweryfikować, czy rzeczywiście przesłany plik to obrazek, czy może ktoś próbuje wrzucić nam na serwer jakieś niepożądane pliki. Tak samo powinniśmy się upewnić, że plik, który jest zwracany to plik, który chcemy pokazać. Jest to jednak temat na oddzielny post.
hej możesz podesłać link na gita odn. Wysyłanie plików na serwer przez Spring Boot bo coś u mnie nie działa
Aktualnie nie mam tego w repo. Jeśli napiszesz jaki masz problem to postaram się pomóc, lub możesz podesłać link do repo gdzie to nie działa to zerknę.
hej a jak moge wyswietlik plik typu png
Możesz użyć przykładowo takiego kodu: