Spring Boot Upload and Resize Images with Imgscalr

Introduction

In this Spring Boot tutorial we learn how to implement a Spring Boot web application that allows users to upload and resize image files by using Spring Boot Web, Thymeleaf, Apache Commons IO and Imgscalr libraries.

Create New Spring Boot Web Project

Open Spring Tool Suite IDE, select menu File > New > Spring Starter Project.

On the New Spring Starter Project popup input new project information as below and click Next.

  • Name: spring-boot-upload-resize
  • Group: dev.simplesolution
  • Artifact: spring-boot-upload-resize
  • Version: 1.0.0
  • Description: Spring Boot Web Upload and Resize
  • Package: dev.simplesolution.uploadresize

Spring Boot Upload and Resize Images with Imgscalr

On the New Spring Starter Project Dependencies popup choose dependencies as below and click Next.

  • Thymeleaf
  • Spring Web

Spring Boot Upload and Resize Images with Imgscalr

Keep the information on the next popup as default and click Finish.

Spring Boot Upload and Resize Images with Imgscalr

You can also creating new Spring Boot project using Spring initializr online tool at start.spring.io

Add Apache Commons IO and Imgscalr libraries to the project

In this step we set up the Apache Commons IO and Imgscalr libraries for the Spring Boot web project.

To use the Apache Commons IO and Imgscalr libraries in the Gradle build project, add the following dependency into the build.gradle file.

implementation 'org.imgscalr:imgscalr-lib:4.2'
implementation 'commons-io:commons-io:2.9.0'

The final build.gradle file is below.

build.gradle

plugins {
	id 'org.springframework.boot' version '2.5.0'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'dev.simplesolution'
version = '1.0.0'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.imgscalr:imgscalr-lib:4.2'
	implementation 'commons-io:commons-io:2.9.0'
	
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

To use the Apache Commons IO and Imgscalr libraries in the Maven build project, add the following dependency into the pom.xml file.

<dependency>
    <groupId>org.imgscalr</groupId>
    <artifactId>imgscalr-lib</artifactId>
    <version>4.2</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.9.0</version>
</dependency>

The final pom.xml file is below.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>dev.simplesolution</groupId>
    <artifactId>spring-boot-upload-resize</artifactId>
    <version>1.0.0</version>
    <name>spring-boot-upload-resize</name>
    <description>Spring Boot Web Upload and Resize</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.imgscalr</groupId>
            <artifactId>imgscalr-lib</artifactId>
            <version>4.2</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Add Application Configurations to application.properties

At this step we add the below configuration to the config file at /src/main/resources/application.properties

application.properties

spring.servlet.multipart.max-file-size=16MB
spring.servlet.multipart.max-request-size=16MB
server.servlet.session.tracking-modes=cookie
image.folder=D:\\SimpleSolution\\Images
image.size=400

  • spring.servlet.multipart.max-file-size to set the maximum upload file size.
  • spring.servlet.multipart.max-request-size to set the maximum request size.
  • server.servlet.session.tracking-modes to allow application transfer session id via cookie.
  • image.folder to set the folder to store uploaded image files.
  • image.size to set the size in pixels of the target resized images.

Implement File Upload Service

Add a new Java package named dev.simplesolution.uploadresize.service, in the created package creates a new interface named FileUploadService as below.

FileUploadService.java

package dev.simplesolution.uploadresize.service;

import java.io.File;

import org.springframework.web.multipart.MultipartFile;

public interface FileUploadService {
	
	File upload(MultipartFile imageFile);

}

Add a new Java package named dev.simplesolution.uploadresize.service.impl, in the created package creates a new class named FileUploadServiceImpl, in this implementation class we read the uploading image from MultipartFile object and write it to the image folder which is setting in the application.properties file.

FileUploadServiceImpl.java

package dev.simplesolution.uploadresize.service.impl;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import dev.simplesolution.uploadresize.service.FileUploadService;

@Service
public class FileUploadServiceImpl implements FileUploadService {

    @Value("${image.folder}")
    private String imageFolder;

    private Logger logger = LoggerFactory.getLogger(FileUploadServiceImpl.class);

    @Override
    public File upload(MultipartFile imageFile) {
        try {
            Path path = Paths.get(imageFolder, imageFile.getOriginalFilename());
            Files.write(path, imageFile.getBytes());
            return path.toFile();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }
}

Implement Resize Image Service

In the Java package dev.simplesolution.uploadresize.service, add a new interface named ImageService as below.

ImageService.java

package dev.simplesolution.uploadresize.service;

import java.io.File;

public interface ImageService {
    boolean resizeImage(File sourceFile);
}

In the Java package dev.simplesolution.uploadresize.service.impl, add a new class named ImageServiceImpl. In this image service class we implement a method to read a given image and resize to a new image with size defined in application.properties file.

ImageServiceImpl.java

package dev.simplesolution.uploadresize.service.impl;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.imageio.ImageIO;

import org.apache.commons.io.FilenameUtils;
import org.imgscalr.Scalr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import dev.simplesolution.uploadresize.service.ImageService;

@Service
public class ImageServiceImpl implements ImageService {

    @Value("${image.folder}")
    private String imageFolder;

    @Value("${image.size}")
    private Integer imageSize;

    private Logger logger = LoggerFactory.getLogger(ImageServiceImpl.class);

    @Override
    public boolean resizeImage(File sourceFile) {
        try {
            BufferedImage bufferedImage = ImageIO.read(sourceFile);
            BufferedImage outputImage = Scalr.resize(bufferedImage, imageSize);
            String newFileName = FilenameUtils.getBaseName(sourceFile.getName())
                    + "_" + imageSize.toString() + "."
                    + FilenameUtils.getExtension(sourceFile.getName());
            Path path = Paths.get(imageFolder,newFileName);
            File newImageFile = path.toFile();
            ImageIO.write(outputImage, "jpg", newImageFile);
            outputImage.flush();
            return true;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            return false;
        }
    }
}

Implement Image Upload Controller

Add a new Java package named dev.simplesolution.uploadresize.controller, add a new class named ImageUploadController, in this class we use the upload service and image service from previous steps to handle upload and resize images.

ImageUploadController.java

package dev.simplesolution.uploadresize.controller;

import java.io.File;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import dev.simplesolution.uploadresize.service.FileUploadService;
import dev.simplesolution.uploadresize.service.ImageService;

@Controller
public class ImageUploadController {

    @Autowired
    private FileUploadService fileUploadService;

    @Autowired
    private ImageService imageService;

    @GetMapping("")
    public String uploadImage() {
        return "uploadImage";
    }

    @PostMapping("/uploadImage")
    public String uploadImage(@RequestParam("image") MultipartFile imageFile, RedirectAttributes redirectAttributes) {
        if(imageFile.isEmpty()) {
            redirectAttributes.addFlashAttribute("errorMessage", "Please choose file to upload.");
            return "redirect:/";
        }

        File file = fileUploadService.upload(imageFile);
        if(file == null) {
            redirectAttributes.addFlashAttribute("errorMessage", "Upload failed.");
            return "redirect:/";

        }
        boolean resizeResult =  imageService.resizeImage(file);
        if(!resizeResult) {
            redirectAttributes.addFlashAttribute("errorMessage", "Resize failed.");
            return "redirect:/";
        }

        redirectAttributes.addFlashAttribute("successMessage", "File upload successfully.");
        return "redirect:/";
    }
}

Create HTML View to Upload Image Files

Create a new HTML view file at /src/main/resources/templates/uploadImage.html to show the form allowing the user choose an image file to upload. In this HTML view we also use the Bootstrap CSS library.

uploadImage.html

<html xmlns:th="https://www.thymeleaf.org">
<head>
    <title>Spring Boot Web Upload and Resize Images</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <h1>Choose an image file to upload and resize.</h1>
    <p class="text-danger" th:if="${errorMessage}" th:text="${errorMessage}"></p>
    <p class="text-success" th:if="${successMessage}" th:text="${successMessage}"></p>
    <form method="POST" enctype="multipart/form-data" action="/uploadImage">
        <div class="form-group">
            <label for="image">File to upload</label>
            <input type="file" class="form-control-file" id="image" name="image" >
        </div>
        <button type="submit" class="btn btn-primary">Upload</button>
    </form>
</div>
</body>
</html>

Final Application

At this step, we have finished implementing the Spring Boot web project to upload and resize images with the source code structure as below screenshot.

Spring Boot Upload and Resize Images with Imgscalr

Run the application and access http://localhost:8080/ you can see the application via browser as below.

Spring Boot Upload and Resize Images with Imgscalr

Choose an image and click the Upload button you will see the upload successful message as below screenshot.

Spring Boot Upload and Resize Images with Imgscalr

Then access the image folder which is setting in application.properties file to see there is the image file uploaded and also a new resized image file.

Spring Boot Upload and Resize Images with Imgscalr

Download Source Code

The source code in this article can be found at: github.com/simplesolutiondev/spring-boot-upload-resize

or clone at:

git clone https://github.com/simplesolutiondev/spring-boot-upload-resize.git

or download at:

Download Source Code

Happy Coding 😊