Spring Boot File Upload and Download with Filesystem

Hey guys in this article, we will learn upload and download the image to a database using Spring Boot and Data JPA. We will create a Spring Boot REST API to upload and download the image. There are two different ways to store the image into the database




Spring boot upload image is one of the most commonly used feature while developing enterprise application using Spring boot. Whenever we have upload/download feature we will create a seprate Spring boot upload image rest api then we will call this inside another function.

In this article we will cover the second way where we will store the direct image into the file system and store the file system path into the database. In the previous article, we already discussed the first approach.

Just to keep this article simple, we will use H2 in-memory database instead of Real database but you can connect to any database for production. You just need to add the database dependency that you are using and data source properties that’s it.

Read More:

Complete Example


We will create this example step by step, follow this tutorial till the end

Create spring boot project


There are many different ways to create a spring boot application, you can follow the below articles to create one –

>> Create spring boot application using Spring initializer
>> Create spring boot application in Spring tool suite [STS]
>> Create spring boot application in IntelliJ IDEA

Add maven dependencies


Open pom.xml and add the following dependencies –

<?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.7.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>in.bushansirgur</groupId>
	<artifactId>image-upload-download</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>image-upload-download</name>
	<description>Spring boot image upload and download project</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</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>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>
  • We have added the spring-boot-starter-web dependency to create web application and REST APIs




  • We have added the spring-boot-starter-data-jpa dependency to perform the database operations.
  • We added an h2 dependency for storing the data in the database, it is a in-memory database.
  • Also we have added the spring-boot-devtools dependency which is for development purpose

Configure Data source


As we discussed above, we will use H2 in-memory database instead of Real database such as MySQL, PostgreSQL or Oracle. Open application.properties file and the following content

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update

Create a JPA Entity


We will create a JPA entity to map the database table with Java object. Create ProductImage.java inside src/main/java and add the following content

package in.bushansirgur.springbootimageupload.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "tbl_product_image")
public class ProductImage {
	
	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String type;
    private String imagePath;
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getImagePath() {
		return imagePath;
	}
	public void setImagePath(String imagePath) {
		this.imagePath = imagePath;
	}
	
    
}
  • We have added @Entity annotation to mark this class as JPA entity
  • We have added @Table annotation to provide the database table information. @Table annotation indicates that this class is mapped with database table tbl_product_image
  • We have also added couple more annotataions @Id and @GeneratedValue annotation.
  • We also added the @Lob annotation for the field imageData which indicate that a persistent property or field should be persisted as a large object to a database-supported large object type.

Create JPA Repository for ProductImage


We will create a Interface and extend it with JpaRepository so the we can use the JpaRepository predefined methods to perform the database operations. Create a interface ProjectImageRepository.java inside src/main/java and add the following content

package in.bushansirgur.springbootimageupload.repository;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import in.bushansirgur.springbootimageupload.entity.ProductImage;

public interface ProductImageRepository extends JpaRepository<ProductImage, Long> {
	
	Optional<ProductImage> findByName(String fileName);
}

We have created a JPA finder method findByName to get the Product image from the database by its image name.



Create a Service class for Product Image


We will create Service class for Product image where will call the JpaRepository methods to save and retrieve the image. While calling the repository methods we will store the file into the file system and store the file path into the database. Similarly while retrieving the image from the database we will read that file into byte[] and return it. Create a class ProductImageService.java under src/main/java and add the following content

package in.bushansirgur.springbootimageupload.service;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import in.bushansirgur.springbootimageupload.entity.ProductImage;
import in.bushansirgur.springbootimageupload.repository.ProductImageRepository;

@Service
public class ProductImageService {
	
	@Autowired
    private ProductImageRepository imageRepo;
	
	private final String PATH = "C:\\workspace\\";
	
	public ProductImage uploadImage(MultipartFile file) throws IOException {
		String fullPath = PATH+file.getOriginalFilename();
		ProductImage pImage = new ProductImage();
		pImage.setName(file.getOriginalFilename());
		pImage.setType(file.getContentType());
		pImage.setImagePath(fullPath);
		
		file.transferTo(new File(fullPath));
		return imageRepo.save(pImage);
	}
	
	public byte[] downloadImage(String fileName) throws IOException{
        Optional<ProductImage> imageObject = imageRepo.findByName(fileName);
        String fullPath = imageObject.get().getImagePath();
        return Files.readAllBytes(new File(fullPath).toPath());
    }
}

Create Controller to expose REST end points for Upload and Download Image


We will create a Controller for ProductImage where we will expose 2 REST end points /upload for uploading the image and /download/{fileName} for downloading the image. Create ProductImageController.java under src/main/java and add the following content

package in.bushansirgur.springbootimageupload.controller;

import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import in.bushansirgur.springbootimageupload.service.ProductImageService;

@RestController
public class ProductImageController {
	
	@Autowired
	private ProductImageService productImageService;
	
	@ResponseStatus(value = HttpStatus.OK)
	@PostMapping("/upload")
	public void uploadImage(@RequestParam("productImage")MultipartFile file) throws IOException{
		productImageService.uploadImage(file);
	}
	
	@GetMapping("/download/{fileName}")
	public ResponseEntity<byte[]> downloadImage(@PathVariable String fileName) throws IOException {
		byte[] image = productImageService.downloadImage(fileName);
		return ResponseEntity.status(HttpStatus.OK).contentType(MediaType.valueOf("image/png")).body(image);
	}
}

Run the app


Run the application using the below maven command –

mvn spring-boot:run

Once the tomcat server is up, open Postman make a HTTP POST request to upload image to the URL http://localhost:8080/upload. In order to send image, inside the HTTP body select form-data, enter productImage as Key and select image which you want to upload as Value.

111

When you send the request, you will see the HTTP status code 200 and you can verify in the database that a new entry has been inserted to the database.

114

Next send the another HTTP GET request to download the image to the URL http://localhost:8080/download/101.png. You will see the image in the response body downloaded from the database.

112

That’s it for this post, if you like this post, share this with your friends and colleagues or you can share this within your social media platform. Thanks, I will see you in our next post.



About the author

Bushan Sirgur

Hey guys, I am Bushan Sirgur from Banglore, India. Currently, I am working as an Associate project in an IT company.

View all posts

Leave a Reply

Your email address will not be published. Required fields are marked *