Through this tutorial, I will guide you how to code file upload functionality in a Java web application based on Spring Boot, Spring Data JPA and Thymeleaf.

Prerequisite: You got familiar with Spring Boot form handling and Spring Data JPA.

Suppose that we have an existing Spring Boot project that includes the user management module. Now we want to update the code to allow the admin to upload photos for users. The create user form would look like this:

create user form

This form, besides text fields, allows the user to pick a file (profile photos) from local computer and when he clicks Save, the file will be uploaded to the server and stored in a separate directory. The name of the file is stored in the database. And you will also learn how to display the uploaded image file in the browser.

 

1. Update Database table and for Entity class

We need to update the users table in the database, adding a new column that stores the file name. Say, the column name is photos:

users table

The data type is varchar(64) so the column can store file name containing up to 64 characters. Then we need to update corresponding entity class User as follows:

@Entity
@Table(name = "users")
public class User {
	
	@Column(nullable = true, length = 64)
	private String photos;

	// other fields and getters, setters are not shown	
}

And no updates required for the UserRepository class.

 

2. Update Web Form for File Upload

Next, we need to update the create new user form to add a file input as follows:

<form th:action="@{/users/save}" 
	th:object="${user}" method="post"
	enctype="multipart/form-data"
	>
	...
	<div>
	
	<label>Photos: </label>
	<input type="file" name="image" accept="image/png, image/jpeg" />
	
	</div>
	...
</form>

Note that we must set the attribute enctype=”multipart/form-data” form the form tag, to tell the browser that this form may contain file upload. And we restrict that only image files can be uploaded using the accept attribute:

<input type="file" name="image" accept="image/png, image/jpeg" />

In case you want to allow uploading any files, do not use this attribute.

 

3. Update Spring Controller to Handle File Upload

On the server side with Spring Boot, we need to update the handler method that is responsible to handle form submission as follows:

@Controller
public class UserController {

	@Autowired 
	private UserRepository repo;
	
	@PostMapping("/users/save")
	public RedirectView saveUser(User user, 
			@RequestParam("image") MultipartFile multipartFile) throws IOException {
		
		String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
		user.setPhotos(fileName);
		
		User savedUser = repo.save(user);

		String uploadDir = "user-photos/" + savedUser.getId();

		FileUploadUtil.saveFile(uploadDir, fileName, multipartFile);
		
		return new RedirectView("/users", true);
	}
}

To handle file uploaded from the client, we need to declare this parameter for the handler method:

@RequestParam("image") MultipartFile multipartFile

The @RequestParam annotation and MultipartFile interface come from the following packages:

import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

That means we don’t have to use any external library for handling file upload. Just use the spring starter web dependency is enough. Under the hood, Spring will use Apache Commons File Upload that parses multipart request to reads data from the file uploaded.

Next, we get the name of the uploaded file, set it to the photos field of the User object, which is then persisted to the database:

String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
user.setPhotos(fileName);
User savedUser = service.save(user);

The class StringUtils come from the package org.springframework.util. Note that we store only the file name in the database table, and the actual uploaded file is stored in the file system:

String uploadDir = "user-photos/" + savedUser.getId();
FileUploadUtil.saveFile(uploadDir, fileName, multipartFile);

Here, the uploaded file is stored in the directory user-photos/userID, which is relative to the application’s directory. And below is the code of the FileUploadUtil class:

package net.codejava;

import java.io.*;
import java.nio.file.*;

import org.springframework.web.multipart.MultipartFile;

public class FileUploadUtil {
	
	public static void saveFile(String uploadDir, String fileName, 
			MultipartFile multipartFile) throws IOException {
		Path uploadPath = Paths.get(uploadDir);
		
		if (!Files.exists(uploadPath)) {
			Files.createDirectories(uploadPath);
		}
		
		try (InputStream inputStream = multipartFile.getInputStream()) {
			Path filePath = uploadPath.resolve(fileName);
			Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
		} catch (IOException ioe) {			
			throw new IOException("Could not save image file: " + fileName, ioe);
		}		
	}
}

As you can see, this utility class is only responsible for creating the directory if not exists, and save the uploaded file from MultipartFile object to a file in the file system.

 

4. Display uploaded images in browser

In case of uploaded files are images, we can display the images in browser with a little configuration. We need to expose the directory containing the uploaded files so the clients (web browsers) can access. Create a configuration file with the following code:

package net.codejava;

import java.nio.file.Path;
import java.nio.file.Paths;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {


	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		exposeDirectory("user-photos", registry);
	}
	
	private void exposeDirectory(String dirName, ResourceHandlerRegistry registry) {
		Path uploadDir = Paths.get(dirName);
		String uploadPath = uploadDir.toFile().getAbsolutePath();
		
		if (dirName.startsWith("../")) dirName = dirName.replace("../", "");
		
		registry.addResourceHandler("/" + dirName + "/**").addResourceLocations("file:/"+ uploadPath + "/");
	}
}

Here, we configure Spring MVC to allow access to the directory user-photos in the file system, with mapping to the application’s context path as /user-photos.

Add a new getter in the entity class User as follows:

@Entity
public class User {
	@Transient
	public String getPhotosImagePath() {
		if (photos == null || id == null) return null;
		
		return "/user-photos/" + id + "/" + photos;
	}
}

Then in the view (HTML with Thymeleaf), we can display an image like this:

<img th:src="/@{${user.photosImagePath}}" />

 

That’s how to implement file upload functionality for an existing Spring Boot application. And in case of images, you learned how to display the images in the browser. To summarize, here are the key points:

  • Add a column to store file name in the database table.
  • Declare a field in the entity class to store name of the uploaded file.
  • Use file input in the web form and set attribute enctype=”multipart/form-data” for the form tag.
  • Use @RequestParam and MultipartFile in Spring controller’s handler method.
  • Use Files.copy() method to copy the uploaded file from temporary location to a fixed directory in the file system.
  • Configure Spring MVC to expose the upload directory so image files can show up in the browser.

If you want to see the coding in action, I recommend you to watch the video below:

 

Related Tutorials: 

 

Other Spring Boot Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Add comment

   


Comments 

#48Thirumala2024-11-27 00:52
it is not displaying image please help me
Quote
#47KELVIN WARUI2023-06-29 04:07
HI the images are uploading successfully but the browser is not showing image on page i get a 403 forbidden error and i have spring security configured
Quote
#46Swati2023-04-11 12:43
Whatever documents we upload can we check that previously uploaded document if exist than show msg duplicate document.
Quote
#45Pratik Madekar2023-03-31 01:31
Hi,
I purchase your Udemy spring boot e-commerce ultimate course and it's a very fantastic tutorial, all the concepts and the major points are mentioned perfectly in the project
I enjoyed the course.

I have a request to you, Can you please provide a fullstack e-commerce project with spring boot + Angular 8 or above version
Quote
#44trushit2023-01-23 06:45
How to delete the stored image?
Quote