Temporary Directory Setup
Before implementing file upload, configure the temporary directory where uploaded files are stored during processing.
Option 1: JVM parameter
mkdir -p /app/tmp
-Djava.io.tmpdir=/app/tmp
Option 2: Spring Boot configuration
spring:
servlet:
multipart:
location: /app/tmp
max-file-size: 500MB
max-request-size: 500MB
Approach One: StandardServletMultipartResolver
This approach leverages Servlet 3.0's native multipart request support.
Java Configuration
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
Configure multipart settings by overriding customizeRegistration method:
package com.example.web.config;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration;
import java.io.IOException;
import java.util.Properties;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {RootConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] {WebConfig.class};
}
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
String tempDir = "/tmp";
long maxFileSize = 5242880;
long maxRequestSize = 5242880;
try {
Properties props = new Properties();
props.load(Thread.currentThread().getContextClassLoader()
.getResourceAsStream("upload.properties"));
tempDir = props.getProperty("temp.directory");
maxFileSize = Long.parseLong(props.getProperty("max.file.size"));
maxRequestSize = Long.parseLong(props.getProperty("max.request.size"));
} catch (IOException e) {
// use defaults
}
registration.setMultipartConfig(
new MultipartConfigElement(tempDir, maxFileSize, maxRequestSize, 0));
boolean success = registration.setInitParameter(
"throwExceptionIfNoHandlerFound", "true");
if (!success) {
throw new RuntimeException("Failed to configure no handler exception");
}
}
}
XML Configuration
<bean id="multipartResolver"
class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<multipart-config>
<location>/var/tmp</location>
<max-file-size>5242880</max-file-size>
<max-request-size>10485760</max-request-size>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
HTML Form
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<form action="/app/upload" enctype="multipart/form-data" method="post">
<input name="attachment" type="file">
<input type="submit" value="Upload">
</form>
</body>
</html>
Controlller Implementations
Option 1: Using byte array (not recommended)
@RequestMapping("/upload")
public Map<String, String> upload(@RequestPart("attachment") byte[] data) throws IOException {
if (data != null && data.length > 0) {
String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String outputPath = "/var/uploads/" + timestamp;
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
fos.write(data);
}
}
Map<String, String> response = new HashMap<>();
response.put("status", "success");
return response;
}
This approach lacks access to the orgiinal filename and content type.
Option 2: Using MultipartFile interface
public interface MultipartFile extends InputStreamSource {
String getName();
String getOriginalFilename();
String getContentType();
boolean isEmpty();
long getSize();
byte[] getBytes() throws IOException;
InputStream getInputStream() throws IOException;
void transferTo(File dest) throws IOException, IllegalStateException;
}
@RequestMapping("/upload")
public Map<String, String> upload(MultipartFile attachment) throws IOException {
if (attachment != null && !attachment.isEmpty()) {
String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String filename = timestamp + "_" + attachment.getOriginalFilename();
File destination = new File("/var/uploads/" + filename);
attachment.transferTo(destination);
}
Map<String, String> response = new HashMap<>();
response.put("status", "success");
return response;
}
Option 3: Using Part interface (Servlet 3.1+)
public interface Part {
InputStream getInputStream() throws IOException;
String getContentType();
String getName();
String getSubmittedFileName();
long getSize();
void write(String fileName) throws IOException;
void delete() throws IOException;
String getHeader(String name);
Collection<String> getHeaders(String name);
Collection<String> getHeaderNames();
}
@RequestMapping("/upload")
public Map<String, String> upload(@RequestPart("attachment") Part filePart) throws IOException {
if (filePart != null && filePart.getSize() > 0) {
String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String targetPath = "/var/uploads/" + timestamp + "_" + filePart.getSubmittedFileName();
filePart.write(targetPath);
}
Map<String, String> response = new HashMap<>();
response.put("status", "success");
return response;
}
Approach Two: CommonsMultipartResolver
This approach requires Apache Commons FileUpload dependencies:
- commons-fileupload.jar
- commons-io.jar
Java Configuration
@Bean
public MultipartResolver multipartResolver() throws IOException {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setUploadTempDir(new FileSystemResource(uploadConfig.tempDirectory()));
resolver.setMaxUploadSize(uploadConfig.maxFileSize());
resolver.setMaxInMemorySize(0);
return resolver;
}
XML Configuration
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<property name="maxInMemorySize" value="4096"/>
<property name="maxUploadSize" value="10485760"/>
</bean>
Complete Upload Controller Example
package com.example.web.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/files")
public class FileUploadController {
@Value("${upload.save.path}")
private String uploadPath;
@PostMapping("/image")
@ResponseBody
public Map<String, Object> uploadImage(
@RequestParam("imageFile") MultipartFile file) {
Map<String, Object> result = new HashMap<>();
try {
if (file.isEmpty()) {
result.put("status", "error");
result.put("message", "File is empty");
return result;
}
String datePath = new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
File directory = new File(uploadPath + datePath);
if (!directory.exists()) {
directory.mkdirs();
}
String originalFilename = file.getOriginalFilename();
File destination = new File(directory, originalFilename);
file.transferTo(destination);
result.put("status", "success");
result.put("path", datePath + originalFilename);
} catch (IllegalStateException | IOException e) {
result.put("status", "error");
result.put("message", e.getMessage());
}
return result;
}
}
HTML Template
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<form th:action="@{/files/image}" method="post"
enctype="multipart/form-data">
<input type="text" name="description" placeholder="Description"/>
<input type="file" name="imageFile">
<button type="submit">Upload</button>
</form>
</body>
</html>