开发者

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

目录
  • 引言
  • 解决方案一:将图片保存为 BLOB 类型直接存入数据库
    • 使用方法:
    • 优点:
    • 缺点:
  • 解决方案二:将图片存储在服务器文件系统,仅保存路径到数据库
    • 使用方法:
    • 优点:
    • 缺点:
  • 解决方案三:使用云存储服务(如阿里云 OSS、AWS S3)
    • 使用方法:
    • 优点:
    • 缺点:
  • 总结对比表格

    引言

    在基于 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 ResponseEnpythontity.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.aliyun编程客栈cs.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("图片已更新");
        }
    }
    

    优点:

    • 支持高并发访问,适合大规模应用场景。
    • 提供丰富的 API 和工具,便于集成和管理。

    缺点:

    • 增加开发复杂度和成本。
    • 对第三方服务依赖较高,存在潜在风险。

    总结对比表格

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

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

    以上就是基于SpringBoot和MySQL实现图片CRUD的三种解决方案的详细内容,更多关于SpringBoot MySQL图片CRUD的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜