java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot MySQL图片CRUD

基于SpringBoot和MySQL实现图片CRUD的三种解决方案

作者:爱的叹息

在基于 Spring Boot 和 MySQL 开发的后端程序中,处理图片的增删改查(CRUD)通常涉及到两个核心部分:存储图片路径信息到数据库和实际文件操作(上传、删除等),以下是几种常见的解决方案,分别详细说明其使用方法,并对比优缺点,需要的朋友可以参考下

引言

在基于 Spring Boot 和 MySQL 开发的后端程序中,处理图片的增删改查(CRUD)通常涉及到两个核心部分:存储图片路径信息到数据库实际文件操作(上传、删除等)。以下是几种常见的解决方案,分别详细说明其使用方法,并对比优缺点

解决方案一:将图片保存为 BLOB 类型直接存入数据库

使用方法:

建表语句示例:

CREATE TABLE book_details (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255),
    image BLOB  -- 存储图片二进制数据
);

Spring Boot 实体类定义:

@Entity
public class BookDetail {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    @Lob
    private byte[] image; // 存储图片的字节数组

    // Getters and Setters
}

Controller 示例代码:

@RestController
@RequestMapping("/books")
public class BookController {

    @Autowired
    private BookRepository bookRepository;

    @PostMapping("/upload")
    public ResponseEntity<String> uploadBookImage(@RequestParam("title") String title, 
                                                 @RequestParam("file") MultipartFile file) throws IOException {
        BookDetail book = new BookDetail();
        book.setTitle(title);
        book.setImage(file.getBytes());
        bookRepository.save(book);
        return ResponseEntity.ok("图片已上传");
    }

    @GetMapping("/image/{id}")
    public ResponseEntity<byte[]> getBookImage(@PathVariable Long id) {
        BookDetail book = bookRepository.findById(id).orElseThrow();
        return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(book.getImage());
    }
}

优点:

缺点:

解决方案二:将图片存储在服务器文件系统,仅保存路径到数据库

使用方法:

建表语句示例:

CREATE TABLE book_details (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255),
    image_path VARCHAR(255)  -- 存储图片路径
);

Spring Boot 实体类定义:

@Entity
public class BookDetail {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String imagePath; // 存储图片的路径

    // Getters and Setters
}

Controller 示例代码:

@RestController
@RequestMapping("/books")
public class BookController {

    @Autowired
    private BookRepository bookRepository;

    // 文件存储目录
    private static final String FILE_DIR = "D:/images/";

    @PostMapping("/upload")
    public ResponseEntity<String> uploadBookImage(@RequestParam("title") String title, 
                                                 @RequestParam("file") MultipartFile file) throws IOException {
        String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
        Path filePath = Paths.get(FILE_DIR, fileName);
        Files.write(filePath, file.getBytes());

        BookDetail book = new BookDetail();
        book.setTitle(title);
        book.setImagePath(filePath.toString());
        bookRepository.save(book);

        return ResponseEntity.ok("图片已上传");
    }

    @GetMapping("/image/{id}")
    public ResponseEntity<Resource> getBookImage(@PathVariable Long id) throws IOException {
        BookDetail book = bookRepository.findById(id).orElseThrow();
        Path path = Paths.get(book.getImagePath());
        Resource resource = new UrlResource(path.toUri());

        if (resource.exists() || resource.isReadable()) {
            return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(resource);
        } else {
            throw new RuntimeException("无法读取图片");
        }
    }

    @DeleteMapping("/delete/{id}")
    public ResponseEntity<String> deleteBookImage(@PathVariable Long id) throws IOException {
        BookDetail book = bookRepository.findById(id).orElseThrow();
        Path path = Paths.get(book.getImagePath());
        if (Files.exists(path)) {
            Files.delete(path);
        }
        bookRepository.delete(book);
        return ResponseEntity.ok("图片已删除");
    }

    @PutMapping("/update/{id}")
    public ResponseEntity<String> updateBookImage(@PathVariable Long id, 
                                              @RequestParam("title") String title, 
                                              @RequestParam("file") MultipartFile file) throws IOException {
        BookDetail book = bookRepository.findById(id).orElseThrow();
        Path oldPath = Paths.get(book.getImagePath());
        if (Files.exists(oldPath)) {
            Files.delete(oldPath);
        }

        String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
        Path newPath = Paths.get(FILE_DIR, fileName);
        Files.write(newPath, file.getBytes());

        book.setTitle(title);
        book.setImagePath(newPath.toString());
        bookRepository.save(book);

        return ResponseEntity.ok("图片已更新");
    }
}

优点:

缺点:

解决方案三:使用云存储服务(如阿里云 OSS、AWS S3)

使用方法:

建表语句示例:

CREATE TABLE book_details (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255),
    image_url VARCHAR(255)  -- 存储云上的图片链接
);

Spring Boot 实体类定义:

@Entity
public class BookDetail {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String imageUrl; // 存储云上的图片链接

    // Getters and Setters
}

Controller 示例代码(以阿里云 OSS 为例):

@RestController
@RequestMapping("/books")
public class BookController {

    @Autowired
    private BookRepository bookRepository;

    // 初始化 OSS 客户端
    private OSS ossClient = new OSSClientBuilder().build("endpoint", "accessKeyId", "accessKeySecret");

    @PostMapping("/upload")
    public ResponseEntity<String> uploadBookImage(@RequestParam("title") String title, 
                                                 @RequestParam("file") MultipartFile file) throws IOException {
        String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
        ossClient.putObject("bucketName", "images/" + fileName, new ByteArrayInputStream(file.getBytes()));

        BookDetail book = new BookDetail();
        book.setTitle(title);
        book.setImageUrl("https://bucketName.oss-cn-region.aliyuncs.com/images/" + fileName);
        bookRepository.save(book);

        return ResponseEntity.ok("图片已上传");
    }

    @DeleteMapping("/delete/{id}")
    public ResponseEntity<String> deleteBookImage(@PathVariable Long id) {
        BookDetail book = bookRepository.findById(id).orElseThrow();
        String url = book.getImageUrl();
        String objectName = url.replace("https://bucketName.oss-cn-region.aliyuncs.com/", "");
        ossClient.deleteObject("bucketName", objectName);
        bookRepository.delete(book);
        return ResponseEntity.ok("图片已删除");
    }

    @PutMapping("/update/{id}")
    public ResponseEntity<String> updateBookImage(@PathVariable Long id, 
                                              @RequestParam("title") String title, 
                                              @RequestParam("file") MultipartFile file) throws IOException {
        BookDetail book = bookRepository.findById(id).orElseThrow();
        String oldUrl = book.getImageUrl();
        String oldObjectName = oldUrl.replace("https://bucketName.oss-cn-region.aliyuncs.com/", "");

        // 删除旧图片
        ossClient.deleteObject("bucketName", oldObjectName);

        // 上传新图片
        String newFileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
        ossClient.putObject("bucketName", "images/" + newFileName, new ByteArrayInputStream(file.getBytes()));

        // 更新数据库
        book.setTitle(title);
        book.setImageUrl("https://bucketName.oss-cn-region.aliyuncs.com/images/" + newFileName);
        bookRepository.save(book);

        return ResponseEntity.ok("图片已更新");
    }
}

优点:

缺点:

总结对比表格

方案存储方式优点缺点适用场景
方案一:BLOB 存储直接将图片存入数据库数据集中管理,易于备份和迁移影响数据库性能,不适用于高并发小规模项目,简单功能
方案二:本地文件系统图片存服务器,路径存数据库减轻数据库压力,易扩展文件管理复杂,需同步更新路径中小型项目,单机部署
方案三:云存储服务图片存云端,URL 存数据库高并发支持,功能丰富开发复杂度高,依赖第三方服务大型项目,分布式架构

根据你的项目规模和技术需求选择合适的方案,可以平衡开发效率、性能和可维护性。

以上就是基于SpringBoot和MySQL实现图片CRUD的三种解决方案的详细内容,更多关于SpringBoot MySQL图片CRUD的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文