Chuyển đến nội dung chính

Spring boot Download and upload File ( phần 1 Backend )

Ở bài viết này mình sẽ trình bày mình sẽ tring bày làm thế nào để upload và download file trong một Restful spring boot web service ( 

Công nghệ sử dụng:
  • Spring Boot
  • Mysql
  • JPA/Hibernate
Content Project:
    Cấu Trúc thư mục :

JPA and MySQL dependencies
  Tôi sẽ lưu trữ file trong mysql database vậy nên cần dependencies về mysql  và jpa. File pom :
<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>

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

Configuring the Database và Multipart File properties

Config : src/main/resources/application.properties file 
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url= jdbc:mysql://localhost:3306/file_demo?useSSL=false
spring.datasource.username= root
spring.datasource.password= 123456

## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update

## Hibernate Logging
logging.level.org.hibernate.SQL= DEBUG


## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB
spring.servlet.multipart.enabled: // cho phép upload multipart

DBFile model

Bây giờ ta tiến hành tạo  DBFile  Model:
package com.example.filedemo.model;

import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;

@Entity
@Table(name = "files")
public class DBFile {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String id;

    private String fileName;

    private String fileType;

    @Lob
    private byte[] data;

    public DBFile() {

    }

    public DBFile(String fileName, String fileType, byte[] data) {
        this.fileName = fileName;
        this.fileType = fileType;
        this.data = data;
    }

    // Getters and Setters (Omitted for brevity) } 
lưu ý rằng: Content file sẽ được lưu trữ dưới dạng byte array trên database


DBFileRepository

Tiếp theo , tôi sẽ tao 1 file DBFileRepositoty để save file to mysql Server:
package com.example.filedemo.repository;

import com.example.filedemo.model.DBFile;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface DBFileRepository extends JpaRepository<DBFile, String> {

}

DBFileStorageService

Tôi sẽ tạo một file  service DBFileStoreService như sau :
package com.example.filedemo.service;

import com.example.filedemo.exception.FileStorageException;
import com.example.filedemo.exception.MyFileNotFoundException;
import com.example.filedemo.model.DBFile;
import com.example.filedemo.repository.DBFileRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;

@Service
public class DBFileStorageService {

    @Autowired
    private DBFileRepository dbFileRepository;

    public DBFile storeFile(MultipartFile file) {
        // Normalize file name
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());

        try {
            // Check if the file's name contains invalid characters
            if(fileName.contains("..")) {
                throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
            }

            DBFile dbFile = new DBFile(fileName, file.getContentType(), file.getBytes());

            return dbFileRepository.save(dbFile);
        } catch (IOException ex) {
            throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
        }
    }

    public DBFile getFile(String fileId) {
        return dbFileRepository.findById(fileId)
                .orElseThrow(() -> new MyFileNotFoundException("File not found with id " + fileId));
    }
}

FileController

Cuối cùng, dưới đây là RestAPI để upload and down load fil
package com.example.filedemo.controller;

import com.example.filedemo.model.DBFile;
import com.example.filedemo.payload.UploadFileResponse;
import com.example.filedemo.service.DBFileStorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class FileController {

    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private DBFileStorageService DBFileStorageService;

    @PostMapping("/uploadFile")
    public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file) {
        DBFile dbFile = DBFileStorageService.storeFile(file);

        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/downloadFile/")
                .path(dbFile.getId())
                .toUriString();

        return new UploadFileResponse(dbFile.getFileName(), fileDownloadUri,
                file.getContentType(), file.getSize());
    }

    @PostMapping("/uploadMultipleFiles")
    public List<UploadFileResponse> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
        return Arrays.asList(files)
                .stream()
                .map(file -> uploadFile(file))
                .collect(Collectors.toList());
    }

    @GetMapping("/downloadFile/{fileId}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileId) {
        // Load file from database
        DBFile dbFile = DBFileStorageService.getFile(fileId);

        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(dbFile.getFileType()))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + dbFile.getFileName() + "\"")
                .body(new ByteArrayResource(dbFile.getData()));
    }

}
Vậy là ta đã cài đặt xong phía backend
Ở bài viết sau ta sẽ hoàn thành project phía frontend
Link tham khảo:Reference
download this project

Nhận xét

Bài đăng phổ biến từ blog này

Eager/Lazy Loading In Hibernate

Eager/Lazy Loading In Hibernate Following technologies being used: Spring Boot 2 Maven Eclipse 1. Introduction Khi làm việc với ORM chắc hẳn các bạn sẽ bắt gặp 2 loại eagerloading lazyloading. Ở bài viết này tôi sẽ trình bày về sự khác biệt giữa hai loại này. 2. Maven Dependencies <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.2.Final</version> </dependency> ở đây chúng ta sử dụng hibernate 5. 3. Eager and Lazy Loading Eager Loading  được thiết kế giúp cho việc khởi tạo đối tượng ngay lập tức. Lazy Loading  được thiết kế giúp cho việc trì hoãn việc khởi tạo đối tưởng miễn là có thể theo dõi ví dụ sau: class  UserLazy @Entity @Table(name = "USER") public class UserLazy implements Serializable { @Id @GeneratedValue @Column(name = "USER_ID") private Long userId; @OneToMany(fetch = FetchType.LAZY, mappedBy ...

Giới thiệu về Sevices và dependency injection trong Angular 7

Sevice là một danh mục rộng bao gồm bất kỳ value, function, hoặc tính năng mà ứng dụng cần. Một service là một class thông thượng được định nghĩa với mục đích rõ ràng. Angurlar phân biệt các thành phần từ các service để tăng tính modul và khả năng tái sử dụng. Một Component có thể giao một số công việc cho các service  như fetching data từ server, validating user input, hoặc logging trực tiếp... Bằng việc xác định xử lý các tiến trình trong một lớp  injectable service class  Bạn sẽ làm các tác vụ đó trở nên có sẵn tới bất kỳ component. Bạn cũng có thể làm ứng dụng của bạn thích ứng hơn bằng cách tiêm nhiều provider của cùng loại dịch vụ. Service examples Dưới đây là một ví dụ show consolog trên browser  src/app/logger.service.ts (class) export class Logger { log(msg: any) { console.log(msg); } error(msg: any) { console.error(msg); } warn(msg: any) { console.warn(msg); } } Service có thể được phụ thuộc vào các Service khác. Theo ví dụ dưới đây , ...