使用minio实现图片和视频的上传

ps:因为业务上遇到了用minio实现图片的上传所以记录一下使用

  • MinIO是一个开源的对象存储服务器,可以用来存储和检索任何类型的文件,包括图片、视频、文档等。MinIO的设计目标是为了提供高性能、高可用性和可扩展性的对象存储服务,同时保持简单易用和低成本。

  • 为啥要用对象存储服务器呢?

    数据库可以存储视频和图片,但是存储大量的视频和图片会占用大量的存储空间,导致数据库变得庞大和缓慢。此外,数据库的主要目的是存储和管理结构化数据,而视频和图片是非结构化数据,因此存储它们可能需要使用不同的技术和工具。因此,通常建议将视频和图片存储在专门的文件系统或云存储中,而不是直接存储在数据库中。

  • MinIO的主要特点包括:

    1. 高性能:MinIO使用Go语言编写,采用了一些优化技术,如并发、异步I/O等,可以实现高性能的对象存储服务。

    2. 高可用性:MinIO支持多副本复制和故障转移等机制,可以保证数据的可靠性和可用性。

    3. 可扩展性:MinIO采用分布式架构,可以通过添加新的节点来扩展存储容量和吞吐量。

    4. 简单易用:MinIO提供了简单易用的API和命令行工具,可以方便地进行对象存储的管理和操作。

    5. 低成本:MinIO可以运行在标准的硬件设备上,不需要专门的存储设备,可以降低存储成本。

    MinIO支持多种API和协议,包括S3、NFS、HDFS、Azure Blob Storage等,可以与各种应用程序和系统集成。此外,MinIO还提供了一些高级功能,如对象锁定、版本控制、事件通知等,可以满足不同的业务需求。

    总之,MinIO是一个功能强大、性能优越、易于使用和低成本的对象存储服务器,适用于各种规模的应用场景。阿里云和腾讯云的oss好像到10G要收费,我认为都可以使用操作都不难。

  • 在使用MinIO的Java SDK时,需要提供以下四个参数:

    1. ENDPOINT:MinIO服务器的地址,包括协议、主机名和端口号。例如,http://localhost:9000表示本地运行的MinIO服务器。

    2. ACCESS_KEY:访问密钥,用于身份验证。在MinIO中,每个用户都有一个访问密钥和一个秘密密钥,用于访问和管理存储桶和对象。

    3. SECRET_KEY:秘密密钥,用于身份验证。与访问密钥一起使用,用于访问和管理存储桶和对象。

    4. BUCKET_NAME:存储桶的名称,用于存储和管理对象。在MinIO中,每个存储桶都有一个唯一的名称。

  • ackage com.atguigu.gmall.product.controller;
    
    import com.atguigu.gmall.common.result.Result;
    import io.minio.BucketExistsArgs;
    import io.minio.MakeBucketArgs;
    import io.minio.MinioClient;
    import io.minio.PutObjectArgs;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.util.UUID;
    
    /**
     * @author 罗峰
     * @version 1.0
     * @description TODO
     * @date 2023-05-07 15:24
     */
    @RestController
    @RequestMapping("admin/product")
    public class FileUploadController {
    
        //  获取文件上传对应的地址
        @Value("${minio.endpointUrl}")
        public String endpointUrl;
    
        @Value("${minio.accessKey}")
        public String accessKey;
    
        @Value("${minio.secreKey}")
        public String secreKey;
    
        @Value("${minio.bucketName}")
        public String bucketName;
    
        //  文件上传控制器
        @PostMapping("fileUpload")
        public Result fileUpload(MultipartFile file) throws Exception{
            //  准备获取到上传的文件路径!
            String url = "";
    
            // 使用MinIO服务的URL,端口,Access key和Secret key创建一个MinioClient对象
            // MinioClient minioClient = new MinioClient("https://play.min.io", "Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG");
            MinioClient minioClient =
                    MinioClient.builder()
                            .endpoint(endpointUrl)
                            .credentials(accessKey, secreKey)
                            .build();
            // 检查存储桶是否已经存在
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if(isExist) {
                System.out.println("Bucket already exists.");
            } else {
                // 创建一个名为asiatrip的存储桶,用于存储照片的zip文件。
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(bucketName)
                        .build());
            }
            //  定义一个文件的名称 : 文件上传的时候,名称不能重复!
            String fileName = System.currentTimeMillis()+ UUID.randomUUID().toString();
            // 使用putObject上传一个文件到存储桶中。
            //  minioClient.putObject("asiatrip","asiaphotos.zip", "/home/user/Photos/asiaphotos.zip");
            minioClient.putObject(
                    PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
                                    file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build());
            //  System.out.println("/home/user/Photos/asiaphotos.zip is successfully uploaded as asiaphotos.zip to `asiatrip` bucket.");
            //  文件上传之后的路径: http://39.99.159.121:9000/gmall/xxxxxx
            url = endpointUrl+"/"+bucketName+"/"+fileName;
    
            System.out.println("url:\t"+url);
            //  将文件上传之后的路径返回给页面!
            return Result.ok(url);
        }
    }
    

    图片是前端传过来的,我们用MultipartFile file来接收,上传到minio之后要把生成的路径传给前端页面显示,但是路径也传到了数据库中。

  • 传图片和视频都是差不多的,但是如果视频涉及到断点续传业务的话会有点复杂。

  • 总结:

  • 1.导入minio的依赖

  • 2.写配置文件,四个参数,用@Value注解注入到处理业务的那层

  • 3.创建一个客户端对象,传入参数,再判断有没有这个桶,没有则创建

  • 4.调用putObject方法实现图片的上传

  • 5.返回路径给前端 ps:数据库那里是用一个大的dto。对象存进去啦,上传图片的component也只是表单的一部分,我们传整个表单的。

猜你喜欢

转载自blog.csdn.net/weixin_65379795/article/details/130586959