В этом уроке мы будем выбирать изображение с помощью Angular 8 UI. Затем это изображение будет отправлено в бэкэнд Spring Boot с помощью вызова REST. Позже это изображение будет храниться в базе данных MySQL. Позже мы также получим сохраненное изображение и отобразим его с помощью Angular.
Сохранение изображения в MYSQL с использованием Spring Boot и Angular 8
Получить изображение из MYSQL, используя Spring Boot и Angular 8
Этот учебник объясняется в видео YouTube ниже.
Угловая установка
Мы будем устанавливать npm и Angular CLI 8
Установите NodeJS, загрузив установочный файл из Install NodeJS . Установите Angular CLI, используя следующую команду. Он получит нам последнюю версию Angular CLI.
Оболочка
xxxxxxxxxx
1
npm install -g @angular/cli
Оболочка
x
1
npm install -g @angular/cli
Мы можем проверить версию Angular CLI:
Оболочка
x
1
ng version
Далее мы создадим новый проект Angular с использованием Angular CLI следующим образом:
Оболочка
xxxxxxxxxx
1
ng new ImageUpload
Чтобы запустить проект Angular CLI, используйте следующую команду. Мы должны зайти в папку ImageUpload и затем использовать ее.
Оболочка
xxxxxxxxxx
1
ng serve
2
Перейти к localhost: 4200.
Я буду использовать Microsoft Visual Studio Code IDE для Angular, чтобы импортировать проект, который мы разработали ранее в Microsoft Visual Studio Code IDE.
Наш окончательный угловой проект будет следующим:
Для этого проекта я буду использовать Bootstrap CSS. Поэтому в index.html добавьте URL для начальной загрузки CSS.
xxxxxxxxxx
1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="utf-8">
5
<title>ImageUpload</title>
6
<base href="/">
7
<meta name="viewport" content="width=device-width, initial-scale=1">
9
<link rel="icon" type="image/x-icon" href="favicon.ico">
10
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
11
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
12
</head>
13
<body>
14
<app-root></app-root>
15
</body>
16
</html>
Угловой компонент для отправки и получения изображения с использованием MySQL
Мы не будем создавать какие-либо новые компоненты и вместо этого изменим существующие компоненты приложения.
Измените app.component.html. Добавьте раздел «Выбор файла», а также раздел, чтобы показать полученное изображение:
Джава
x
1
<div class="container row">
2
<div class="col-md-12">
3
<h1>Upload Image</h1>
4
</div>
5
</div>
6
<div class="container row">
7
<div class="col-md-6">
8
<input type="file" (change)="onFileChanged($event)">
9
</div>
10
<div class="col-md-6">
11
<input type="button" (click)="onUpload()" value="upload">
12
</div>
13
</div>
14
<hr />
15
<div class="container row">
16
<div class="col-md-12">
17
<div *ngIf=message>{{message}}</div>
18
</div>
19
</div>
20
<div class="container row">
22
<div class="col-md-6">
23
<input type="text" class="form-control" id="name" placeholder="image name" [(ngModel)]="imageName"
24
name="name" />
25
</div>
26
<div class="col-md-6">
27
<input type="button" (click)="getImage()" value="Get Image">
28
</div>
29
</div>
30
<div class="container row">
32
<div class="col-md-12">
33
<div *ngIf=retrievedImage>
34
<img [src]="retrievedImage">
35
</div>
36
</div>
37
</div>
Затем измените файл машинного текста компонента приложения.
Джава
xxxxxxxxxx
1
import { HttpClient, HttpEventType } from '@angular/common/http';
2
import { Component } from '@angular/core';
3
({
5
selector: 'app-root',
6
templateUrl: './app.component.html',
7
styleUrls: ['./app.component.css'],
8
})
9
export class AppComponent {
11
constructor(private httpClient: HttpClient) { }
12
selectedFile: File;
13
retrievedImage: any;
14
base64Data: any;
15
retrieveResonse: any;
16
message: string;
17
imageName: any;
18
//Gets called when the user selects an image
20
public onFileChanged(event) {
22
//Select File
23
this.selectedFile = event.target.files[0];
24
}
25
//Gets called when the user clicks on submit to upload the image
27
onUpload() {
28
console.log(this.selectedFile);
29
//FormData API provides methods and properties to allow us easily prepare form data to be sent with POST HTTP requests.
30
const uploadImageData = new FormData();
31
uploadImageData.append('imageFile', this.selectedFile, this.selectedFile.name);
32
//Make a call to the Spring Boot Application to save the image
33
this.httpClient.post('http://localhost:8080/image/upload', uploadImageData, { observe: 'response' })
34
.subscribe((response) => {
35
if (response.status === 200) {
36
this.message = 'Image uploaded successfully';
37
} else {
38
this.message = 'Image not uploaded successfully';
39
}
40
}
41
);
42
}
43
//Gets called when the user clicks on retieve image button to get the image from back end
45
getImage() {
46
//Make a call to Sprinf Boot to get the Image Bytes.
47
this.httpClient.get('http://localhost:8080/image/get/' + this.imageName)
48
.subscribe(
49
res => {
50
this.retrieveResonse = res;
51
this.base64Data = this.retrieveResonse.picByte;
52
this.retrievedImage = 'data:image/jpeg;base64,' + this.base64Data;
53
}
54
);
55
}
56
}
Измените app.module.ts, чтобы включить необходимые модули, например HttpClientModule и FormsModule-
Джава
xxxxxxxxxx
1
import { BrowserModule } from '@angular/platform-browser';
2
import { NgModule } from '@angular/core';
3
import { AppRoutingModule } from './app-routing.module';
4
import { AppComponent } from './app.component';
5
import { HttpClientModule } from '@angular/common/http';
6
import { FormsModule } from '@angular/forms';
7
({
10
declarations: [
11
AppComponent
12
],
13
imports: [
15
BrowserModule,
16
AppRoutingModule,
17
HttpClientModule,
18
FormsModule
19
],
20
providers: [],
22
bootstrap: [AppComponent]
23
})
24
export class AppModule { }
Spring Boot Module для сохранения и получения изображений с использованием MySQL
Проект Maven будет следующим:
Файл pom.xml будет содержать веб-ресурсы Spring и зависимости данных.
XML
xxxxxxxxxx
1
2
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4
<modelVersion>4.0.0</modelVersion>
6
<groupId>com.javainuse</groupId>
7
<artifactId>boot-image-upload</artifactId>
8
<version>0.0.1-SNAPSHOT</version>
9
<packaging>jar</packaging>
10
<name>boot-jdbc</name>
13
<description>Demo project for Spring Boot</description>
14
<parent>
15
<groupId>org.springframework.boot</groupId>
16
<artifactId>spring-boot-starter-parent</artifactId>
17
<version>2.0.1.RELEASE</version>
18
<relativePath /> <!-- lookup parent from repository -->
19
</parent>
20
<properties>
22
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
24
<java.version>1.8</java.version>
25
</properties>
26
<dependencies>
28
<dependency>
29
<groupId>org.springframework.boot</groupId>
30
<artifactId>spring-boot-starter-web</artifactId>
31
</dependency>
32
<dependency>
33
<groupId>org.springframework.boot</groupId>
34
<artifactId>spring-boot-starter-data-jpa</artifactId>
35
</dependency>
36
<dependency>
37
<groupId>mysql</groupId>
38
<artifactId>mysql-connector-java</artifactId>
39
<scope>runtime</scope>
40
</dependency>
41
</dependencies>
42
<build>
44
<plugins>
45
<plugin>
46
<groupId>org.springframework.boot</groupId>
47
<artifactId>spring-boot-maven-plugin</artifactId>
48
</plugin>
49
</plugins>
50
</build>
51
</project>
Создайте класс модели с именем ImageModel
:
Джава
xxxxxxxxxx
1
package com.javainuse.model;
2
import javax.persistence.*;
3
5
name = "image_table") (
6
public class ImageModel {
7
public ImageModel() {
9
super();
10
}
11
public ImageModel(String name, String type, byte[] picByte) {
13
this.name = name;
14
this.type = type;
15
this.picByte = picByte;
16
}
17
19
name = "id") (
20
strategy = GenerationType.IDENTITY) (
21
private Long id;
22
name = "name") (
23
private String name;
24
name = "type") (
25
private String type;
26
//image bytes can have large lengths so we specify a value
28
//which is more than the default length for picByte column
29
name = "picByte", length = 1000) (
30
private byte[] picByte;
32
public String getName() {
33
return name;
34
}
35
public void setName(String name) {
37
this.name = name;
38
}
39
public String getType() {
41
return type;
42
}
43
public void setType(String type) {
45
this.type = type;
46
}
47
public byte[] getPicByte() {
49
return picByte;
50
}
51
public void setPicByte(byte[] picByte) {
53
this.picByte = picByte;
54
}
55
}
Создайте JPARepository для хранения и получения изображений:
Джава
x
1
package com.javainuse.db;
2
import java.util.Optional;
4
import org.springframework.data.jpa.repository.JpaRepository;
5
import com.javainuse.model.ImageModel;
6
public interface ImageRepository extends JpaRepository<ImageModel, Long> {
8
Optional<ImageModel> findByName(String name);
9
}
Создайте класс контроллера:
- Предоставьте POST API для получения файла Multipart и сохранения байтов для него в MySQL с помощью репозитория JPA. Multipart происходит от MIME, интернет-стандарта, расширяющего формат электронных писем. Это то, что браузеры используют для загрузки файлов через HTML-формы.
- Предоставьте GET API для извлечения байтов изображения из MySQL с помощью репозитория JPA и его возврата.
- Поскольку байты изображения велики, мы используем алгоритмы сжатия и распаковки.
Джава
xxxxxxxxxx
1
package com.javainuse.controller;
2
import java.io.ByteArrayOutputStream;
4
import java.io.IOException;
5
import java.util.Optional;
6
import java.util.zip.DataFormatException;
7
import java.util.zip.Deflater;
8
import java.util.zip.Inflater;
9
import org.springframework.beans.factory.annotation.Autowired;
10
import org.springframework.http.HttpStatus;
11
import org.springframework.http.ResponseEntity;
12
import org.springframework.http.ResponseEntity.BodyBuilder;
13
import org.springframework.web.bind.annotation.CrossOrigin;
14
import org.springframework.web.bind.annotation.GetMapping;
15
import org.springframework.web.bind.annotation.PathVariable;
16
import org.springframework.web.bind.annotation.PostMapping;
17
import org.springframework.web.bind.annotation.RequestMapping;
18
import org.springframework.web.bind.annotation.RequestParam;
19
import org.springframework.web.bind.annotation.RestController;
20
import org.springframework.web.multipart.MultipartFile;
21
import com.javainuse.db.ImageRepository;
22
import com.javainuse.model.ImageModel;
23
25
origins = "http://localhost:4200") (
26
path = "image") (
27
public class ImageUploadController {
28
30
ImageRepository imageRepository;
31
"/upload") (
32
public BodyBuilder uplaodImage( ("imageFile") MultipartFile file) throws IOException {
33
System.out.println("Original Image Byte Size - " + file.getBytes().length);
35
ImageModel img = new ImageModel(file.getOriginalFilename(), file.getContentType(),
36
compressBytes(file.getBytes()));
37
imageRepository.save(img);
38
return ResponseEntity.status(HttpStatus.OK);
39
}
40
path = { "/get/{imageName}" }) (
42
public ImageModel getImage( ("imageName") String imageName) throws IOException {
43
final Optional<ImageModel> retrievedImage = imageRepository.findByName(imageName);
44
ImageModel img = new ImageModel(retrievedImage.get().getName(), retrievedImage.get().getType(),
45
decompressBytes(retrievedImage.get().getPicByte()));
46
return img;
47
}
48
// compress the image bytes before storing it in the database
50
public static byte[] compressBytes(byte[] data) {
51
Deflater deflater = new Deflater();
52
deflater.setInput(data);
53
deflater.finish();
54
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
55
byte[] buffer = new byte[1024];
56
while (!deflater.finished()) {
57
int count = deflater.deflate(buffer);
58
outputStream.write(buffer, 0, count);
59
}
60
try {
61
outputStream.close();
62
} catch (IOException e) {
63
}
64
System.out.println("Compressed Image Byte Size - " + outputStream.toByteArray().length);
65
return outputStream.toByteArray();
66
}
67
// uncompress the image bytes before returning it to the angular application
69
public static byte[] decompressBytes(byte[] data) {
70
Inflater inflater = new Inflater();
71
inflater.setInput(data);
72
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
73
byte[] buffer = new byte[1024];
74
try {
75
while (!inflater.finished()) {
76
int count = inflater.inflate(buffer);
77
outputStream.write(buffer, 0, count);
78
}
79
outputStream.close();
80
} catch (IOException ioe) {
81
} catch (DataFormatException e) {
82
}
83
return outputStream.toByteArray();
84
}
85
}
Создайте файл application.properties, где мы указываем свойства базы данных:
Джава
xxxxxxxxxx
1
spring.datasource.url=jdbc:mysql://localhost/bootdb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
2
spring.datasource.username=root
3
spring.datasource.password=root
4
spring.datasource.platform=mysql
5
spring.datasource.initialization-mode=always
6
spring.jpa.hibernate.ddl-auto=update
Наконец, создайте класс начальной загрузки, используя аннотацию SpringBoot:
Джава
1
package com.javainuse;
2
import org.springframework.boot.SpringApplication;
4
import org.springframework.boot.autoconfigure.SpringBootApplication;
5
7
public class ImageUploadApplication {
8
public static void main(String[] args) {
10
SpringApplication.run(ImageUploadApplication.class, args);
11
}
12
}
Запустите приложение Spring Boot
Перейдите на localhost: 4200, выберите изображение для загрузки и нажмите кнопку загрузки. Если изображение было успешно загружено, мы отобразим сообщение, что изображение было успешно загружено. В консоли Spring Boot мы видим размер полученного изображения. Также в MySQL мы можем видеть изображение, сохраненное в виде байтов в таблице с именем image_model. Для получения изображения введите имя изображения, которое необходимо получить, и нажмите кнопку «Получить изображение».