1. Introduction
Dans ce tutoriel rapide, nous allons apprendre comment télécharger un fichier en utilisant Spring Boot.
Voyons comment le faire à travers une soumission de formulaire.
2. Pourquoi les téléchargements de fichiers sont-ils importants ?
Le téléchargement de fichiers est un cas d’utilisation très courant pour les applications web modernes, par exemple, l’ajout de documents dans des formulaires ou le téléchargement de photos de profil. Bien que cela soit simple à comprendre, gérer des fichiers correctement présente certaines difficultés. Par exemple, exposer une application sans contraintes sur la taille des fichiers que les utilisateurs peuvent télécharger peut submerger notre application ou consommer tout le stockage disponible. Par conséquent, avant d’accepter un fichier, nous devons valider son type et son contenu et gérer les échecs avec aisance.
Donc, dans notre application, nous allons utiliser les options offertes par Spring Boot pour la rendre robuste en imposant une limite sur la taille des fichiers et en fournissant un retour afin que l’utilisateur comprenne ce qui se passe.
3. Flux de Téléversement
Le diagramme de séquence suivant montre visuellement les interactions entre l’Utilisateur, le Navigateur et notre application Spring Boot :
Sorry, it seems there was no content provided for translation. Please provide the text you would like me to translate into French.
4. Configuration de Maven
Commençons par inclure nos dépendances. Assurons-nous d’obtenir les dernières versions de spring-boot-starter-web et spring-boot-starter-thymeleaf.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>3.4.2</version>
</dependency>
</dependencies>
Pour un nouveau projet, il est préférable de commencer par le Spring Initializr et d’inclure ces dépendances :
Spring Web
: framework MVC et Tomcat intégréThymeleaf
: Un moteur de templates Java moderne côté serveur pour les environnements web et autonomes.
5. Mise en œuvre du téléchargement de fichiers
Commençons à mettre en œuvre notre application.
5.1 Formulaire de téléversement dans Thymeleaf
Tout d’abord, nous allons créer un modèle Thymeleaf qui comprend un formulaire de base avec un champ de fichier et un bouton pour soumettre le formulaire à notre point de terminaison.
Nous devons créer un fichier file-upload.html
dans un dossier appelé templates
au sein du dossier des ressources de l’application :
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mini.css/3.0.1/mini-default.min.css">
</head>
<body>
<div class="container">
<header>
<h2>File Upload</h2>
</header>
<main>
<form action="#" th:action="@{/upload}" method="post" enctype="multipart/form-data">
<div class="input-group vertical">
<input type="file" name="file" required>
<button type="submit">Upload</button>
</div>
</form>
<div th:if="${message}" class="alert"
th:classappend="${message.contains('Success') ? 'alert-success' : 'alert-error'}"
th:text="${message}"></div>
</main>
</div>
</body>
</html>
enctype=multipart/form-data
. Sans cela, le navigateur n’enverra pas le fichier sous forme de données multipart, et le téléchargement ne fonctionnera pas comme prévu.Après le formulaire, nous avons ajouté un espace réservé pour afficher des messages.
Dans notre modèle, nous utilisons mini.css afin de ne pas avoir à gérer le style de l’application tout en évitant l’apparence par défaut du navigateur.
C’est tout pour le côté front-end.
5.2. Configuration du stockage
Ensuite, nous devons décider où enregistrer les fichiers téléchargés par nos utilisateurs. Ajoutons une propriété files.upload-dir
dans le fichier application.properties
:
server.port=8090
files.upload-dir=./uploadedfiles
C’est l’endroit où nous allons sauvegarder les fichiers.
5.3 Contrôleur de Téléversement de Fichier
Maintenant, nous allons implémenter un contrôleur nommé FileUploadController
qui expose un point de terminaison pour servir le modèle que nous avons créé au navigateur :
@Controller
public class FileUploadController {
@GetMapping("/")
public String fileUpload() {
return "file-upload";
}
}
Nous devons simplement nous assurer que la chaîne que nous retournons correspond au nom du modèle que nous avons créé précédemment.
Ensuite, dans le même contrôleur, nous allons créer un point de terminaison POST /upload
pour gérer les demandes de téléchargement de fichiers. Ce point de terminaison utilisera un MultipartFile
comme paramètre de requête pour obtenir le fichier. MultipartFile
est une interface qui étend InputStreamSource
:
@Value("${files.upload-dir}")
private String uploadDir;
@PostMapping("/upload")
public String handleUpload(
@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes
) {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "Please select a file");
return "redirect:/";
}
try {
String filename = StringUtils.cleanPath(file.getOriginalFilename());
Path destination = Paths.get(uploadDir, filename);
Files.createDirectories(destination.getParent());
file.transferTo(destination);
redirectAttributes.addFlashAttribute("message", "Success: " + filename + " (" + file.getSize() + " bytes)");
return "redirect:/";
} catch (IOException e) {
redirectAttributes.addFlashAttribute("message", "Error: " + e.getMessage());
return "redirect:/";
}
}
En bref, d’abord, nous obtenons le nom du fichier à partir de l’objet d’entrée file
. Ensuite, nous créons les dossiers nécessaires pour enregistrer destination
en utilisant StringUtils.cleanPath
afin de prévenir les attaques simples de traversée de chemin. Ensuite, nous enregistrons les données du fichier entrant dans destination
et envoyons un message de succès. En cas d’échec, nous informons l’utilisateur en conséquence, juste pour qu’il sache ce qui se passe.
Dans le contrôleur, nous avons également injecté le répertoire de téléchargement en utilisant @Value
et implémenté une méthode @PostMapping
qui prend le MultipartFile
ainsi qu’un objet RedirectAttributes
. L’interface RedirectAttributes
dans Spring MVC est utilisée pour passer des données lors d’une redirection. Plus précisément, nous avons utilisé addFlashAttribute
pour sauvegarder le message dans la session de manière temporaire, afin qu’il soit disponible après la redirection lorsque le template est traité, permettant ainsi d’afficher le retour d’information correct.
StringUtils.cleanPath
ne doit pas être utilisé comme une méthode de sécurité. D’autres mécanismes doivent être employés pour prévenir les problèmes de traversée de chemin.Maintenant, si nous exécutons l’application en utilisant mvn spring-boot:run
et que nous allons sur localhost:8090
, nous devrions voir notre formulaire et être en mesure de télécharger des fichiers de petite taille.
6. Gestion des gros fichiers
Nous pouvons maintenant télécharger des petits fichiers sans aucun problème. Mais si la taille du fichier est supérieure à 1 Mo (la limite par défaut), notre application échouera, et le navigateur pourrait afficher une erreur. Si nous voulons permettre aux utilisateurs de télécharger des fichiers plus volumineux, nous pouvons configurer un seuil plus élevé.
6.1 Configurer la taille maximale des fichiers
Pour configurer la taille de fichier maximale autorisée, nous modifions les propriétés spring.servlet.multipart.max-file-size
et spring.servlet.multipart.max-request-size
dans application.properties
:
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=11MB
Cela ne suffit pas à lui seul. Nous devons également configurer notre conteneur de servlets afin qu’il n’abandonne pas une connexion si la requête entrante dépasse sa valeur maximale par défaut avant que la gestion des multipart de Spring ne prenne effet.
Notre application Spring Boot utilise par défaut Tomcat intégré. Nous pouvons le configurer pour accepter des requêtes POST de taille plus grande (ou effectivement illimitée) afin que les vérifications de taille soient gérées uniquement par la configuration multipart de Spring :
server.tomcat.max-http-form-post-size=-1
server.tomcat.max-swallow-size=-1
Maintenant, si nous essayons de télécharger des fichiers de plus de 10 Mo, Spring MVC empêchera le téléchargement, mais le comportement par défaut pourrait toujours aboutir à une page d’erreur non gérée (comme une page d’erreur Whitelabel affichant une erreur 500 liée à MaxUploadSizeExceededException
). Si nous souhaitons personnaliser ce comportement afin que l’interaction dans l’UI soit plus fluide, nous pouvons ajouter une gestion des erreurs personnalisée.
6.2 Gestion des erreurs personnalisée
En arrière-plan, Spring MVC déclenche une MaxUploadSizeExceededException
lorsqu’un fichier dépasse la limite de taille configurée. Nous pouvons créer un @ControllerAdvice
pour attraper MultipartException
globalement et gérer ces erreurs avec élégance. Nous attrapons MultipartException
car MaxUploadSizeExceededException
l’étend, nous permettant de traiter d’autres erreurs potentielles liées au multipart également :
@ControllerAdvice
public class FileUploadExceptionHandler {
@ExceptionHandler(MultipartException.class)
public String handleSizeExceeded(RedirectAttributes attrs) {
attrs.addFlashAttribute("message",
"File exceeds size limit!");
return "redirect:/";
}
}
La configuration d’un @ControllerAdvice
offre un moyen centralisé de gérer les exceptions à travers plusieurs contrôleurs et de renvoyer des messages d’erreur conviviaux ou de rediriger avec un retour d’information approprié.
7. Conseils pour les Environnements de Production
Bien que ce tutoriel explique un téléchargement de fichier simple, il existe plusieurs considérations supplémentaires pour les environnements de production qui ne sont pas abordées ici.
Tout d’abord, nous ne limitons pas le type de fichiers autorisés pour le téléchargement. Nous pourrions résoudre cela par une simple vérification de l’extension de fichier ou mettre en œuvre une validation plus approfondie, comme vérifier le type MIME ou scanner à la recherche de virus et de logiciels malveillants.
Dans des environnements de production où de grands fichiers sont attendus, nous devrions envisager d’utiliser une approche de streaming pour éviter de charger l’intégralité du fichier en mémoire sur le serveur. En alternative, nous pourrions considérer l’utilisation de téléversements par morceaux depuis le côté client, où le fichier est divisé en parties plus petites, téléversées séparément, puis réassemblées côté serveur.
8. Conclusion
Dans cet article, nous avons appris à implémenter le téléchargement de fichiers dans Spring Boot en utilisant un simple formulaire HTML, Thymeleaf et un contrôleur Spring MVC. Nous avons également découvert comment configurer des limites pour les fichiers volumineux et personnaliser le processus de gestion des erreurs pour les exceptions de taille.
Vous pouvez trouver le code complet sur GitHub.