Minio的快速使用

MinIO核心概念

下面介绍MinIO中的几个核心概念,这些概念在所有的对象存储服务中也都是通用的。

  • 对象(Object)

    对象是实际的数据单元,例如我们上传的一个图片。

  • 存储桶(Bucket)

    存储桶是用于组织对象的命名空间,类似于文件夹。每个存储桶可以包含多个对象。

  • 端点(Endpoint)

    端点是MinIO服务器的网络地址,用于访问存储桶和对象,例如http://192.168.10.101:9000

    注意:

    9000为MinIO的API的默认端口,前边配置的9001以为管理页面端口。

  • Access Key 和 Secret Key

    Access Key是用于标识和验证访问者身份的唯一标识符,相当于用户名。

    Secret Key是与Access Key关联的密码,用于验证访问者的身份

使用案例

  • 第一步:导入依赖(注意选择版本)

     <dependency>
         <groupId>io.minio</groupId>
         <artifactId>minio</artifactId>
     </dependency>

  • 第二步:在配置文件中添加必要参数

    application.yml中配置Minio的endpointaccessKeysecretKeybucketName等参数

     minio:
       endpoint: http://<hostname>:<port>
       access-key: <access-key>
       secret-key: <secret-key>
       bucket-name: <bucket-name>

    注意:上述<hostname><port>等信息需根据实际情况进行修改。

  • 第三步:创建配置类

    1. 在合适的位置创建MinioProperties,如com.lease.common.minio.MinioProperties内容包括:

       @ConfigurationProperties(prefix = "minio")
       @Data
       public class MinioProperties {
       ​
           private String endpoint;
       ​
           private String accessKey;
       ​
           private String secretKey;
           
           private String bucketName;
       }

    2. 在合适的位置创建MinioConfiguration,如com.lease.common.minio.MinioConfiguration,内容如下:

       @Configuration
       @EnableConfigurationProperties(MinioProperties.class)
       public class MinioConfiguration {
       ​
           @Autowired
           private MinioProperties properties;
       ​
           @Bean
           public MinioClient minioClient() {
               return MinioClient.builder().endpoint(properties.getEndpoint()).credentials(properties.getAccessKey(), properties.getSecretKey()).build();
           }
       }

  • 第四步:开发上传接口

    • 编写Controller层逻辑

      FileUploadController中增加如下内容

       @Tag(name = "文件管理")
       @RequestMapping("/admin/file")
       @RestController
       public class FileUploadController {
       ​
           @Autowired
           private FileService service;
       ​
           @Operation(summary = "上传文件")
           @PostMapping("upload")
           public Result<String> upload(@RequestParam MultipartFile file) {
       ​
               String url = service.upload(file);
               return Result.ok(url);
           }
       }

      说明:MultipartFile是Spring框架中用于处理文件上传的类,它包含了上传文件的信息(如文件名、文件内容等)。

    • 编写Service层逻辑

      • FileService中增加如下内容

         String upload(MultipartFile file);
      • FileServiceImpl中增加如下内容

         @Autowired
         private MinioProperties properties;
         ​
         @Autowired
         private MinioClient client;
         ​
         @Override
         public String upload(MultipartFile file) {
         ​
             try {
                 boolean bucketExists = client.bucketExists(BucketExistsArgs.builder().bucket(properties.getBucketName()).build());
                 if (!bucketExists) {
                     client.makeBucket(MakeBucketArgs.builder().bucket(properties.getBucketName()).build());
                     client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(properties.getBucketName()).config(createBucketPolicyConfig(properties.getBucketName())).build());
                 }
         ​
                 String filename = new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/" + UUID.randomUUID() + "-" + file.getOriginalFilename();
                 client.putObject(PutObjectArgs.builder().
                         bucket(properties.getBucketName()).
                         object(filename).
                         stream(file.getInputStream(), file.getSize(), -1).
                         contentType(file.getContentType()).build());
         ​
                 return String.join("/", properties.getEndpoint(), properties.getBucketName(), filename);
         ​
             } catch (Exception e) {
                 e.printStackTrace();
             }
             return null;
         }
         ​
         private String createBucketPolicyConfig(String bucketName) {
         ​
             return """
                     {
                       "Statement" : [ {
                         "Action" : "s3:GetObject",
                         "Effect" : "Allow",
                         "Principal" : "*",
                         "Resource" : "arn:aws:s3:::%s/*"
                       } ],
                       "Version" : "2012-10-17"
                     }
                     """.formatted(bucketName);
         }
        

        注意

        上述createBucketPolicyConfig方法的作用是生成用于描述指定bucket访问权限的JSON字符串。最终生成的字符串格式如下,其表示,允许(Allow)所有人(*)获取(s3:GetObject)指定桶(<bucket-name>)的内容。

         {
           "Statement" : [ {
             "Action" : "s3:GetObject",
             "Effect" : "Allow",
             "Principal" : "*",
             "Resource" : "arn:aws:s3:::<bucket-name>/*"
           } ],
           "Version" : "2012-10-17"
         }

        将其设置为所有人可访问。

      • 异常处理

        • 问题解决思路

          为保证前端能够接收到正常的错误提示信息,应该将Service方法的异常抛出到Controller方法中,然后在Controller方法中对异常进行捕获并处理。具体操作如下

          Service层代码

           @Override
           public String upload(MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException{
           ​
               boolean bucketExists = minioClient.bucketExists(
                       BucketExistsArgs.builder()
                               .bucket(properties.getBucketName())
                               .build());
               if (!bucketExists) {
                   minioClient.makeBucket(
                           MakeBucketArgs.builder()
                                   .bucket(properties.getBucketName())
                                   .build());
                   minioClient.setBucketPolicy(
                           SetBucketPolicyArgs.builder()
                                   .bucket(properties.getBucketName())
                                   .config(createBucketPolicyConfig(properties.getBucketName()))
                                   .build());
               }
               String filename = new SimpleDateFormat("yyyyMMdd").format(new Date()) +
                       "/" + UUID.randomUUID() + "-" + file.getOriginalFilename();
               minioClient.putObject(
                       PutObjectArgs.builder()
                               .bucket(properties.getBucketName())
                               .stream(file.getInputStream(), file.getSize(), -1)
                               .object(filename)
                               .contentType(file.getContentType())
                               .build());
           ​
               return String.join("/",properties.getEndpoint(),properties.getBucketName(),filename);
           }

          Controller层代码

           public Result<String> upload(@RequestParam MultipartFile file) {
               try {
                   String url = service.upload(file);
                   return Result.ok(url);
               } catch (Exception e) {
                   e.printStackTrace();
                   return Result.fail();
               }
           }

        • 全局异常处理

          按照上述写法,所有的Controller层方法均需要增加try-catch逻辑,使用Spring MVC提供的全局异常处理功能,可以将所有处理异常的逻辑集中起来,进而统一处理所有异常,使代码更容易维护。

          具体用法如下,详细信息可参考官方文档

          common模块中创建common.exception.GlobalExceptionHandler类,内容如下

           @ControllerAdvice
           public class GlobalExceptionHandler {
           ​
               @ExceptionHandler(Exception.class)
               @ResponseBody
               public Result error(Exception e){
                   e.printStackTrace();
                   return Result.fail();
               }
           }

          上述代码中的关键注解的作用如下

          @ControllerAdvice用于声明处理全局Controller方法异常的类

          @ExceptionHandler用于声明处理异常的方法,value属性用于声明该方法处理的异常类型

          @ResponseBody表示将方法的返回值作为HTTP的响应体

          注意:

          全局异常处理功能由SpringMVC提供,因此需要在common模块pom.xml中引入如下依赖

           <!--spring-web-->
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-web</artifactId>
           </dependency>

        • 修改Controller层代码

          由于前文的GlobalExceptionHandler会处理所有Controller方法抛出的异常,因此Controller层就无需关注异常的处理逻辑了,因此Controller层代码可做出如下调整。

          public Result<String> upload(@RequestParam MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
               String url = service.upload(file);
             return Result.ok(url);
           }

报错说明

Non-XML response from server

检查docker

 d4257a14c9a7        minio/minio:RELEASE.2023-12-02T10-51-33Z   "/usr/bin/docker-ent…"   6 months ago        Up 7 hours          0.0.0.0:9005->9000/tcp, 0.0.0.0:9006->9090/tcp                                               lottery-minio

有两个端口 一个是浏览器访问客户端用的,另外一个是java api访问用的,改了配置文件里面的端口就解决了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值