Bestand uploaden is een zeer gebruikelijke taak in elke webtoepassing. We hebben eerder gezien hoe we bestanden kunnen uploaden in Servlet en Struts2 Bestand Uploaden. Vandaag zullen we meer te weten komen over Spring Bestand uploaden, specifiek Spring MVC Bestand Uploaden voor enkele en meerdere bestanden.
Spring MVC Bestand Uploaden
Het Spring MVC-framework biedt ondersteuning voor het uploaden van bestanden door integratie met de Apache Commons FileUpload API. Het proces om bestanden te uploaden is zeer eenvoudig en vereist eenvoudige configuraties. We zullen een eenvoudig Spring MVC-project maken in STS dat eruit zal zien zoals de onderstaande afbeelding. Het grootste deel is boilerplate-code gegenereerd door de STS-tool. We zullen ons concentreren op de wijzigingen die nodig zijn om de integratie van Spring-bestandsupload te benutten.
Maven-afhankelijkheden voor Apache Commons FileUpload
Ten eerste moeten we Apache Commons FileUpload-afhankelijkheden toevoegen aan ons pom.xml-bestand, zodat de vereiste JAR-bestanden deel uitmaken van de webtoepassing. Hieronder staat het afhankelijkheidssnippet uit mijn pom.xml-bestand.
<!-- 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>
Weergaven van Spring-bestandsuploadformulieren
We zullen twee JSP-pagina’s maken om enkelvoudige en meervoudige bestandsuploads in de Spring-webtoepassing mogelijk te maken. Code voor de weergave 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 voor de weergave 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>
Merk op dat deze bestanden eenvoudige HTML-bestanden zijn. Ik gebruik geen JSP- of Spring-tags om complexiteit te vermijden. Het belangrijke punt om op te merken is dat het attribuut enctype van het formulier multipart/form-data moet zijn, zodat de Spring-webtoepassing weet dat het verzoek bestandsgegevens bevat die moeten worden verwerkt. Let ook op dat voor meerdere bestanden het formulierveld “file” en “name” hetzelfde zijn in de invoervelden, zodat de gegevens in de vorm van een array worden verzonden. We zullen de invoerarray nemen, de bestandsgegevens analyseren en deze opslaan onder de opgegeven bestandsnaam.
Spring MVC Multipart Configuratie
Om Apache Commons FileUpload te gebruiken voor het verwerken van multipart verzoeken, hoeven we alleen de multipartResolver
bean te configureren met de klasse als org.springframework.web.multipart.commons.CommonsMultipartResolver
. Ons uiteindelijke Spring configuratiebestand ziet er als volgt uit. servlet-context.xml code:
<?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>
Let op dat ik de maximale uploadgrootte instel door de maxUploadSize eigenschapswaarde voor de multipartResolver bean te geven. Als je naar de broncode van de DispatcherServlet
klasse kijkt, zie je dat er een MultipartResolver variabele met de naam multipartResolver wordt gedefinieerd en geïnitialiseerd in de onderstaande methode.
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");
}
}
Met deze configuratie zal elk verzoek met enctype als multipart/form-data worden afgehandeld door multipartResolver voordat het wordt doorgegeven aan de Controller klasse.
Spring Bestand Upload Controller Klasse
De controller klasse code is heel eenvoudig, we moeten handler methoden definiëren voor de uploadFile en uploadMultipleFile URI’s. FileUploadController.java code:
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();
// Het maken van de map om het bestand op te slaan
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "tmpFiles");
if (!dir.exists())
dir.mkdirs();
// Het bestand maken op de server
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();
// Het maken van de map om het bestand op te slaan
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "tmpFiles");
if (!dir.exists())
dir.mkdirs();
// Het bestand maken op de server
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;
}
}
Let op het gebruik van Spring-annotaties die ons leven gemakkelijker maken en de code leesbaarder maken. De methode uploadFileHandler
wordt gebruikt om het scenario voor het uploaden van één bestand af te handelen, terwijl de methode uploadMultipleFileHandler
wordt gebruikt om het scenario voor het uploaden van meerdere bestanden af te handelen. Eigenlijk zouden we een enkele methode kunnen hebben om beide scenario’s af te handelen. Exporteer nu de applicatie als WAR-bestand en implementeer het in de Tomcat-servletcontainer. Wanneer we onze applicatie uitvoeren, tonen onderstaande afbeeldingen ons de verzoeken en reacties.
Voorbeeld van bestandsuploaden met Spring MVC
Je kunt de serverlogs controleren om te weten waar de bestanden zijn opgeslagen. Download het project via de bovenstaande link en speel er wat mee om meer te leren.