Search Tutorials


Upload and Get Images using Spring Boot + Angular8 + MySQL | JavaInUse



   

Upload and Get Images using Spring Boot + Angular8 + MySQL

In this tutorial we will be selecting an image using Angular8 UI. This image will then be sent to the Spring Boot back end by making REST call. Later this image will be stored in MySQL database. We will also later retrieve the saved image and display it using Angular.

Store Image in MYSQL using Spring Boot + Angular 8


angular 8 spring boot fulstack store image mysql

Retrieve Image from MYSQL using Spring Boot + Angular 8


angular 8 spring boot fulstack get image mysql

Video

This tutorial is explained in the below Youtube Video.

Angular Setup

We will be installing npm and angular cli 8
  • Install node js by downloading the installable from Install NodeJS
  • install angular cli using the following command.It wll get us the latest version of angular cli.
    	npm install -g @angular/cli
    	

    angular cli 8 install
  • We can check the angular cli version -
    	ng version
    	

    angular cli 8 version
  • Next we will create a new angular project using the angular cli as follows-
    	ng new ImageUpload
        

    angular cli 8 new project
  • To get the angular cli project started use the following command. We must go inside the ImageUpload folder and then use it.
        ng serve
        

    angular cli 8 start
Go to localhost:4200
angular 8 hello world
I will be using the Miscrosoft Visual Studio Code IDE for angular. So import the project we developed earlier in Miscrosoft Visual Studio Code IDE.
Our final angular project will be as follows-
angular 8 application
For this project is will be making use of Bootstrap CSS. So in the index.html  add the url for the bootstrap css.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>ImageUpload</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" 
 integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

</head>
<body>
  <app-root></app-root>
</body>
</html>

Angular Component to Send and Retrieve Image using MySQL

We will be not be creating any new component and instead modify the existing app component.
Modify the app.component.html. Add the File Selector section and also a section to show the retrieved image -
<div class="container row">
    <div class="col-md-12">
        <h1>Upload Image</h1>
    </div>
</div>

<div class="container row">
    <div class="col-md-6">
        <input type="file" (change)="onFileChanged($event)">

    </div>
    <div class="col-md-6">
        <input type="button" (click)="onUpload()" value="upload">
    </div>
</div>
<hr />
<div class="container row">
    <div class="col-md-12">
        <div *ngIf=message>{{message}}</div>
    </div>
</div>

<div class="container row">
    <div class="col-md-6">
        <input type="text" class="form-control" id="name" placeholder="image name" [(ngModel)]="imageName"
            name="name" />
    </div>
    <div class="col-md-6">
        <input type="button" (click)="getImage()" value="Get Image">

    </div>
</div>

<div class="container row">
    <div class="col-md-12">
        <div *ngIf=retrievedImage>
            <img [src]="retrievedImage">
        </div>
    </div>
</div>
Next modify the app component typescript file.
import { HttpClient, HttpEventType } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})

export class AppComponent {
  constructor(private httpClient: HttpClient) { }

  selectedFile: File;
  retrievedImage: any;
  base64Data: any;
  retrieveResonse: any;
  message: string;
  imageName: any;

  //Gets called when the user selects an image
  public onFileChanged(event) {
    //Select File
    this.selectedFile = event.target.files[0];
  }


  //Gets called when the user clicks on submit to upload the image
  onUpload() {
    console.log(this.selectedFile);
    
    //FormData API provides methods and properties to allow us easily prepare form data to be sent with POST HTTP requests.
    const uploadImageData = new FormData();
    uploadImageData.append('imageFile', this.selectedFile, this.selectedFile.name);
  
    //Make a call to the Spring Boot Application to save the image
    this.httpClient.post('http://localhost:8080/image/upload', uploadImageData, { observe: 'response' })
      .subscribe((response) => {
        if (response.status === 200) {
          this.message = 'Image uploaded successfully';
        } else {
          this.message = 'Image not uploaded successfully';
        }
      }
      );


  }

    //Gets called when the user clicks on retieve image button to get the image from back end
    getImage() {
    //Make a call to Sprinf Boot to get the Image Bytes.
    this.httpClient.get('http://localhost:8080/image/get/' + this.imageName)
      .subscribe(
        res => {
          this.retrieveResonse = res;
          this.base64Data = this.retrieveResonse.picByte;
          this.retrievedImage = 'data:image/jpeg;base64,' + this.base64Data;
        }
      );
  }
}
Modify app.module.ts to include the required modules i.e HttpClientModule and FormsModule-
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Spring Boot Module to save and retrieve images using MySQL

The Maven project will be as follow-
angular8 spring boot maven
The pom.xml will contain the Spring web and data 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.javainuse</groupId>
	<artifactId>boot-image-upload</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>boot-jdbc</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
	</dependencies>

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


</project>
Create the model class named ImageModel-
package com.javainuse.model;

import javax.persistence.*;

@Entity
@Table(name = "image_table")
public class ImageModel {

	public ImageModel() {
		super();
	}

	public ImageModel(String name, String type, byte[] picByte) {
		this.name = name;
		this.type = type;
		this.picByte = picByte;
	}

	@Id
	@Column(name = "id")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(name = "name")
	private String name;

	@Column(name = "type")
	private String type;

    //image bytes can have large lengths so we specify a value
    //which is more than the default length for picByte column
	@Column(name = "picByte", length = 1000)
	private byte[] picByte;

	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 byte[] getPicByte() {
		return picByte;
	}

	public void setPicByte(byte[] picByte) {
		this.picByte = picByte;
	}
}
Create the JPARepository for storing and retrieving images -
package com.javainuse.db;

import java.util.Optional;

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

import com.javainuse.model.ImageModel;

public interface ImageRepository extends JpaRepository<ImageModel, Long> {
	Optional<ImageModel> findByName(String name);
}

Create the controller class-
  • Expose a POST API for receiving the Multipart file and storing the bytes for the same in mysql using the JPA repository. Multipart originates from MIME, an Internet standard that extends the format of emails. It is what browsers use to upload files through HTML forms.
  • Expose a GET API for retrieving the image bytes from mysql using the JPA repository and returning it
  • Also as the image bytes are large we make use of the compression and decompression alogorithms
package com.javainuse.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Optional;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.ResponseEntity.BodyBuilder;
import org.springframework.web.bind.annotation.CrossOrigin;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.javainuse.db.ImageRepository;
import com.javainuse.model.ImageModel;

@RestController
@CrossOrigin(origins = "http://localhost:4200")
@RequestMapping(path = "image")
public class ImageUploadController {

	@Autowired
	ImageRepository imageRepository;

	@PostMapping("/upload")
	public BodyBuilder uplaodImage(@RequestParam("imageFile") MultipartFile file) throws IOException {

		System.out.println("Original Image Byte Size - " + file.getBytes().length);
		ImageModel img = new ImageModel(file.getOriginalFilename(), file.getContentType(),
				compressBytes(file.getBytes()));
		imageRepository.save(img);
		return ResponseEntity.status(HttpStatus.OK);
	}

	@GetMapping(path = { "/get/{imageName}" })
	public ImageModel getImage(@PathVariable("imageName") String imageName) throws IOException {

		final Optional<ImageModel> retrievedImage = imageRepository.findByName(imageName);
		ImageModel img = new ImageModel(retrievedImage.get().getName(), retrievedImage.get().getType(),
				decompressBytes(retrievedImage.get().getPicByte()));
		return img;
	}

	// compress the image bytes before storing it in the database
	public static byte[] compressBytes(byte[] data) {
		Deflater deflater = new Deflater();
		deflater.setInput(data);
		deflater.finish();

		ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
		byte[] buffer = new byte[1024];
		while (!deflater.finished()) {
			int count = deflater.deflate(buffer);
			outputStream.write(buffer, 0, count);
		}
		try {
			outputStream.close();
		} catch (IOException e) {
		}
		System.out.println("Compressed Image Byte Size - " + outputStream.toByteArray().length);

		return outputStream.toByteArray();
	}

	// uncompress the image bytes before returning it to the angular application
	public static byte[] decompressBytes(byte[] data) {
		Inflater inflater = new Inflater();
		inflater.setInput(data);
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
		byte[] buffer = new byte[1024];
		try {
			while (!inflater.finished()) {
				int count = inflater.inflate(buffer);
				outputStream.write(buffer, 0, count);
			}
			outputStream.close();
		} catch (IOException ioe) {
		} catch (DataFormatException e) {
		}
		return outputStream.toByteArray();
	}
}
Create the application.properties where we specify the database properties-
spring.datasource.url=jdbc:mysql://localhost/bootdb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.platform=mysql
spring.datasource.initialization-mode=always
spring.jpa.hibernate.ddl-auto=update
Finally create the bootstrap class using SpringBoot annotation-
package com.javainuse;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ImageUploadApplication {

	public static void main(String[] args) {
		SpringApplication.run(ImageUploadApplication.class, args);
	}

}
Start the Spring Boot Application- Go to localhost:4200

angular spring boot upload image
Select the image to be uploaded and click on upload button. If the image is uploaded successfully then we will display message that image has been uploaded successfully
angular spring boot mysql upload image
In the spring boot console we can see the size of the image recieved.
angular8 spring boot full stack
Also in MySQL we can see the image saved as bytes in the tabled named image_model.
image saved in bytes in mysql
For retrieving the image, enter the name of the image to be retrieved and click on Get Image button.
angular spring boot show image

Download Source Code

Download it -
Spring Boot + Image Upload
Angular8 + Image Upload

See Also

Spring Boot Hello World Application- Create simple controller and jsp view using Maven Spring Boot Tutorial-Spring Data JPA Spring Boot + Simple Security Configuration Pagination using Spring Boot Simple Example Spring Boot + ActiveMQ Hello world Example Spring Boot + Swagger Example Hello World Example Spring Boot + Swagger- Understanding the various Swagger Annotations Spring Boot Main Menu Spring Boot Interview Questions