В этом уроке мы будем выбирать изображение с помощью 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. Для получения изображения введите имя изображения, которое необходимо получить, и нажмите кнопку «Получить изображение».