Exemplo de Upload com Spring Boot 3

Exemplo de Upload com Spring Boot 3

Neste tutorial, você verá:

✔️ Spring Boot 3 com Thymeleaf para renderização da página.
✔️ Spring MVC para lidar com requisições de upload e remoção.
✔️ Armazenamento local das imagens na pasta uploads/.
✔️ Front-end responsivo com Thymeleaf para exibir e excluir imagens.

📌 Simplifique seu processo de deploy com o nosso painel ICP!

Hoje, eu vou te mostrar como criar um projeto simples em Spring Boot 3 para realizar upload de imagens para o servidor e usar em seu projeto.

📌 Passo 1: Criar o Projeto Spring Boot

Crie um novo projeto Spring Boot 3 no Spring Initializr ( https://start.spring.io/ ) com as seguintes dependências:

  • Spring Web
  • Thymeleaf
  • Spring Boot DevTools

📌 Passo 2: Estrutura do Projeto:

A estrutura do projeto ficará assim:

upload-springboot/
│── src/main/java/host/integrator/upload/
│   ├── UploadApplication.java
│   ├── controller/
│   │   ├── UploadController.java
│── src/main/resources/
│   ├── static/uploads/        # Pasta onde as imagens serão salvas
│   ├── templates/index.html   # Página com formulário e galeria de imagens
│── pom.xml        

📌 Passo 3: Criar o Controlador

package com.example.upload.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
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;

@Controller
public class UploadController {

    private static final String UPLOAD_DIR = "src/main/resources/static/uploads/";

    // Página inicial com lista de imagens
    @GetMapping("/")
    public String index(Model model) {
        File uploadFolder = new File(UPLOAD_DIR);
        List<String> images = uploadFolder.exists() ?
                Arrays.stream(uploadFolder.list())
                        .map(filename -> "/uploads/" + filename)
                        .collect(Collectors.toList()) : List.of();
        
        model.addAttribute("images", images);
        return "index";
    }

    // Upload de imagem
    @PostMapping("/upload")
    public String uploadImage(@RequestParam("image") MultipartFile file) {
        if (!file.isEmpty()) {
            try {
                File uploadDir = new File(UPLOAD_DIR);
                if (!uploadDir.exists()) uploadDir.mkdirs();
                
                Path path = Paths.get(UPLOAD_DIR + file.getOriginalFilename());
                Files.write(path, file.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "redirect:/";
    }

    // Excluir imagem
    @PostMapping("/delete")
    public String deleteImage(@RequestParam("filename") String filename) {
        File file = new File(UPLOAD_DIR + filename);
        if (file.exists()) file.delete();
        return "redirect:/";
    }
}

📌 Passo 4: : Criar o Front-end com Thymeleaf

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload de Imagens</title>
    <style>
        body { display: flex; flex-direction: column; align-items: center; font-family: Arial, sans-serif; margin: 20px; }
        form { display: flex; flex-direction: column; align-items: center; gap: 10px; }
        .gallery { display: flex; flex-wrap: wrap; justify-content: center; gap: 15px; margin-top: 20px; }
        .image-container { position: relative; }
        img { width: 150px; height: 150px; object-fit: cover; border-radius: 5px; }
        button { padding: 8px 15px; border: none; cursor: pointer; border-radius: 5px; }
        .upload-btn { background: blue; color: white; }
        .upload-btn:hover { background: darkblue; }
        .delete-btn { position: absolute; top: 5px; right: 5px; background: red; color: white; width: 25px; height: 25px; border-radius: 50%; font-size: 14px; display: flex; align-items: center; justify-content: center; }
        .delete-btn:hover { background: darkred; }
    </style>
</head>
<body>

<h1>Upload de Imagens</h1>

<form action="/upload" method="POST" enctype="multipart/form-data">
    <input type="file" name="image" accept="image/*" required>
    <button type="submit" class="upload-btn">Enviar</button>
</form>

<h2 th:if="${images.size() > 0}">Imagens Enviadas</h2>
<div class="gallery" th:if="${images.size() > 0}">
    <div class="image-container" th:each="image : ${images}">
        <img th:src="${image}" alt="Imagem">
        <form action="/delete" method="POST">
            <input type="hidden" name="filename" th:value="${#strings.substringAfter(image, '/uploads/')}">
            <button type="submit" class="delete-btn">X</button>
        </form>
    </div>
</div>

</body>
</html>

📌 Passo 4: : Execute o seu projeto e terá esse resultado

Valeu pessoal, até a próxima.