Le téléchargement de fichiers est une tâche très courante dans toute application web. Nous avons déjà vu comment télécharger des fichiers dans Servlet et télécharger des fichiers dans Struts2. Aujourd’hui, nous allons parler du téléchargement de fichiers avec Spring, en particulier du téléchargement de fichiers avec Spring MVC pour des fichiers simples et multiples.
Téléchargement de fichiers avec Spring MVC
Le framework Spring MVC prend en charge le téléchargement de fichiers en intégrant l’API Apache Commons FileUpload. Le processus de téléchargement de fichiers est très simple et nécessite des configurations simples. Nous allons créer un projet Spring MVC simple dans STS qui ressemblera à l’image ci-dessous. La plupart du code est généré automatiquement par l’outil STS, nous allons nous concentrer sur les modifications nécessaires pour utiliser l’intégration du téléchargement de fichiers avec Spring.
Dépendances Maven pour Apache Commons FileUpload
Tout d’abord, nous devons ajouter les dépendances Apache Commons FileUpload dans notre fichier pom.xml, afin que les fichiers jar requis fassent partie de l’application web. Voici un extrait de dépendance de mon fichier pom.xml.
<!-- Apache Commons FileUpload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- Apache Commons IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
Vues de formulaire de téléchargement de fichiers Spring
Nous créerons deux pages JSP pour permettre le téléchargement de fichiers unique et multiple dans une application web Spring. Code de la vue upload.jsp :
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Upload File Request Page</title>
</head>
<body>
<form method="POST" action="uploadFile" enctype="multipart/form-data">
File to upload: <input type="file" name="file"><br />
Name: <input type="text" name="name"><br /> <br />
<input type="submit" value="Upload"> Press here to upload the file!
</form>
</body>
</html>
Code de la vue uploadMultiple.jsp :
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Upload Multiple File Request Page</title>
</head>
<body>
<form method="POST" action="uploadMultipleFile" enctype="multipart/form-data">
File1 to upload: <input type="file" name="file"><br />
Name1: <input type="text" name="name"><br /> <br />
File2 to upload: <input type="file" name="file"><br />
Name2: <input type="text" name="name"><br /> <br />
<input type="submit" value="Upload"> Press here to upload the file!
</form>
</body>
</html>
Remarquez que ces fichiers sont des fichiers HTML simples, je n’utilise pas de balises JSP ou Spring pour éviter la complexité. Le point important à noter est que l’attribut enctype du formulaire doit être multipart/form-data, afin que l’application web Spring sache que la requête contient des données de fichier à traiter. Notez également que pour plusieurs fichiers, les champs de formulaire « file » et « name » sont identiques dans les champs de saisie, de sorte que les données seront envoyées sous forme de tableau. Nous prendrons le tableau d’entrée, analyserons les données du fichier et les stockerons dans le nom de fichier donné.
Configuration de l’envoi multipartie Spring MVC
Pour utiliser Apache Commons FileUpload pour gérer les requêtes multiparties, il suffit de configurer la balise multipartResolver
avec la classe org.springframework.web.multipart.commons.CommonsMultipartResolver
. Notre fichier de configuration Spring final ressemble à ce qui suit. Code servlet-context.xml :
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/**" location="/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- setting maximum upload size -->
<beans:property name="maxUploadSize" value="100000" />
</beans:bean>
<context:component-scan base-package="com.journaldev.spring.controller" />
</beans:beans>
Remarquez que je définis la limite de taille maximale de téléchargement en fournissant la valeur de propriété maxUploadSize pour la balise multipartResolver. Si vous examinez le code source de la classe DispatcherServlet
, vous verrez qu’une variable MultipartResolver nommée multipartResolver est définie et initialisée dans la méthode ci-dessous.
private void initMultipartResolver(ApplicationContext context)
{
try
{
this.multipartResolver = ((MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class));
if (this.logger.isDebugEnabled()) {
this.logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
}
}
catch (NoSuchBeanDefinitionException ex)
{
this.multipartResolver = null;
if (this.logger.isDebugEnabled())
this.logger.debug("Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided");
}
}
Avec cette configuration, toute demande avec enctype en tant que multipart/form-data sera traitée par multipartResolver avant d’être transmise à la classe du contrôleur.
Classe du contrôleur de téléchargement de fichiers Spring
Le code de la classe du contrôleur est très simple, nous devons définir des méthodes de gestion pour les URI uploadFile et uploadMultipleFile. Code FileUploadController.java :
package com.journaldev.spring.controller;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
/**
* Handles requests for the application file upload requests
*/
@Controller
public class FileUploadController {
private static final Logger logger = LoggerFactory
.getLogger(FileUploadController.class);
/**
* Upload single file using Spring Controller
*/
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public @ResponseBody
String uploadFileHandler(@RequestParam("name") String name,
@RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
// Création du répertoire pour stocker le fichier
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "tmpFiles");
if (!dir.exists())
dir.mkdirs();
// Créer le fichier sur le serveur
File serverFile = new File(dir.getAbsolutePath()
+ File.separator + name);
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(serverFile));
stream.write(bytes);
stream.close();
logger.info("Server File Location="
+ serverFile.getAbsolutePath());
return "You successfully uploaded file=" + name;
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
} else {
return "You failed to upload " + name
+ " because the file was empty.";
}
}
/**
* Upload multiple file using Spring Controller
*/
@RequestMapping(value = "/uploadMultipleFile", method = RequestMethod.POST)
public @ResponseBody
String uploadMultipleFileHandler(@RequestParam("name") String[] names,
@RequestParam("file") MultipartFile[] files) {
if (files.length != names.length)
return "Mandatory information missing";
String message = "";
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
String name = names[i];
try {
byte[] bytes = file.getBytes();
// Création du répertoire pour stocker le fichier
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "tmpFiles");
if (!dir.exists())
dir.mkdirs();
// Créer le fichier sur le serveur
File serverFile = new File(dir.getAbsolutePath()
+ File.separator + name);
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(serverFile));
stream.write(bytes);
stream.close();
logger.info("Server File Location="
+ serverFile.getAbsolutePath());
message = message + "You successfully uploaded file=" + name
+ "
";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
}
return message;
}
}
Remarquez l’utilisation des annotations Spring qui facilitent notre vie et rendent le code plus lisible. La méthode uploadFileHandler
est utilisée pour gérer le téléchargement de fichiers unique tandis que la méthode uploadMultipleFileHandler
est utilisée pour gérer le téléchargement de plusieurs fichiers. En fait, nous pourrions avoir une seule méthode pour gérer les deux scénarios. Exportez maintenant l’application sous forme de fichier WAR et déployez-la dans le conteneur de servlets Tomcat. Lorsque nous exécutons notre application, les images ci-dessous nous montrent les requêtes et les réponses.
Exemple de téléchargement de fichiers Spring MVC
Vous pouvez vérifier les journaux du serveur pour connaître l’emplacement où les fichiers ont été stockés. Téléchargez le projet depuis le lien ci-dessus et jouez avec pour en apprendre davantage.