minio安装、与springboot整合

介绍

MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。

安装

Windows安装包安装

1、下载exe文件下载链接

2、cmd运行脚本: .\minio.exe server D:\html\minio(为minion运行目录,文件上传到这里)

linux环境docker安装

1、拉取docker镜像

docker search minio
docker pull minio/minio

2、启动容器

docker run -itd -p 9000:9000 
--name minio   
-e "MINIO_ACCESS_KEY=admin"   
-e "MINIO_SECRET_KEY=admin"   
-v /mnt/data:/data   
-v /mnt/config:/root/.minio  
minio/minio server /data

安装完成,访问9000端口即可打开web页面进行操作

整合springboot

1、依赖

<!--minio对象存储-->
<dependency>
  <groupId>io.minio</groupId>
  <artifactId>minio</artifactId>
  <version>7.1.4</version>
</dependency>

2、配置yml minio参数

#minio
minio:
  endpoint: 127.0.0.1
  port: 9000
  accessKey: admin
  secretKey: admin
  secure: false

3、配置minio客户端

属性类

@Data
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
    private String endpoint;
    private int port;
    private String accessKey;
    private String secretKey;
    private Boolean secure;
}

配置类

@Configuration
@EnableConfigurationProperties({MinioProperties.class})
public class MinioConfiguration {

    @Autowired
    private MinioProperties properties;

    @Bean
    MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(properties.getEndpoint(),properties.getPort(),properties.getSecure())
                .credentials(properties.getAccessKey(),properties.getSecretKey())
                .build();
    }
}

工具类

@Slf4j
@Component
public class MinioHelper {

    @Autowired
    private MinioClient minioClient;

    private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;

    /**检查存储桶是否存在*/
    @SneakyThrows
    public boolean bucketExists(String bucketName) {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**创建存储桶*/
    @SneakyThrows
    public boolean makeBucket(String bucketName) {
        boolean flag = bucketExists(bucketName);
        if (!flag) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            return true;
        }
        return false;
    }

    /**列出所有存储桶名称*/
    public List<String> listBucketNames() {
        List<Bucket> bucketList = listBuckets();
        List<String> bucketListName = new ArrayList<>();
        for (Bucket bucket : bucketList) {
            bucketListName.add(bucket.name());
        }
        return bucketListName;
    }

    /**列出所有存储桶*/
    @SneakyThrows
    public List<Bucket> listBuckets() {
        return minioClient.listBuckets();
    }

    /**删除存储桶*/
    @SneakyThrows
    public void removeBucket(String bucketName) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        Iterable<Result<Item>> myObjects = listObjects(bucketName);
        for (Result<Item> result : myObjects) {
            Item item = result.get();
            AssertUtils.assertTrue(item.size() > 0,SystemCode.BIZ_EXCEPTION,"bucket有对象文件,删除失败");
        }
        // 删除存储桶,注意,只有存储桶为空时才能删除成功。
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        flag = bucketExists(bucketName);
        AssertUtils.assertFalse(flag,SystemCode.BIZ_EXCEPTION,"bucket未成功删除");
    }

    /**列出存储桶中的所有对象名称*/
    @SneakyThrows
    public List<String> listObjectNames(String bucketName) {
        List<String> listObjectNames = new ArrayList<>();
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        Iterable<Result<Item>> myObjects = listObjects(bucketName);
        for (Result<Item> result : myObjects) {
            Item item = result.get();
            listObjectNames.add(item.objectName());
        }
        return listObjectNames;
    }

    /**列出存储桶中的所有对象*/
    @SneakyThrows
    public Iterable<Result<Item>> listObjects(String bucketName) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        return minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(bucketName)
                .recursive(false)
                .includeUserMetadata(false)
                .useApiVersion1(false)
                .build());
    }

    /**通过文件上传到对象*/
    @SneakyThrows
    public boolean putObject(String bucketName, String objectName, String fileName) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build());
        ObjectStat statObject = statObject(bucketName, objectName);
        return statObject != null && statObject.length() > 0;
    }

    /**文件上传*/
    @SneakyThrows
    public void putObject(String bucketName, MultipartFile multipartFile, String filename) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        PutObjectOptions options = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
        options.setContentType(multipartFile.getContentType());
        InputStream stream = multipartFile.getInputStream();
        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(filename).stream(
                stream, options.objectSize(), options.partSize())
                .contentType(options.contentType())
                .headers(options.headers())
                .sse(options.sse())
                .build());
    }

    /**通过InputStream上传对象*/
    @SneakyThrows
    public boolean putObject(String bucketName, String objectName, InputStream stream) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        PutObjectOptions options = new PutObjectOptions(stream.available(), -1);
        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
                stream, options.objectSize(), options.partSize())
                .contentType(options.contentType())
                .headers(options.headers())
                .sse(options.sse())
                .build());
        ObjectStat statObject = statObject(bucketName, objectName);
        return statObject != null && statObject.length() > 0;
    }

    /**以流的形式获取一个文件对象*/
    @SneakyThrows
    public InputStream getObject(String bucketName, String objectName) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        ObjectStat statObject = statObject(bucketName, objectName);
        if (statObject != null && statObject.length() > 0) {
            InputStream stream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
            return stream;
        }
        return null;
    }

    /**以流的形式获取一个文件对象(断点下载)*/
    @SneakyThrows
    public InputStream getObject(String bucketName, String objectName, long offset, Long length) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        ObjectStat statObject = statObject(bucketName, objectName);
        if (statObject != null && statObject.length() > 0) {
            InputStream stream = minioClient.getObject(GetObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .offset(offset)
                    .length(length)
                    .build());
            return stream;
        }
        return null;
    }

    /**下载并将文件保存到本地*/
    @SneakyThrows
    public boolean getObject(String bucketName, String objectName, String fileName) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        ObjectStat statObject = statObject(bucketName, objectName);
        if (statObject != null && statObject.length() > 0) {
            minioClient.downloadObject(DownloadObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .filename(fileName)
                    .build());
            return true;
        }
        return false;
    }

    /**删除一个对象*/
    @SneakyThrows
    public void removeObject(String bucketName, String objectName) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表*/
    @SneakyThrows
    public List<String> removeObject(String bucketName, List<String> objectNames) {
        List<String> deleteErrorNames = new ArrayList<>();
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        Stream<DeleteObject> stream = StreamSupport.stream(objectNames.spliterator(), false)
              .map(name -> new DeleteObject(name));
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(stream::iterator).build());
        for (Result<DeleteError> result : results) {
            DeleteError error = result.get();
            deleteErrorNames.add(error.objectName());
        }
        return deleteErrorNames;
    }

    /**生成一个给HTTP GET请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。*/
    @SneakyThrows
    public String presignedGetObject(String bucketName, String objectName, Integer expires) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
            throw new InvalidExpiresRangeException(expires,
                    "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
        }
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expires)
                        .build());
    }

    /**生成一个给HTTP PUT请求用的presigned URL。
     * 浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天*/
    @SneakyThrows
    public String presignedPutObject(String bucketName, String objectName, Integer expires) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
            throw new InvalidExpiresRangeException(expires,
                    "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
        }
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.PUT)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expires)
                        .build());
    }

    /**获取对象的元数据*/
    @SneakyThrows
    public ObjectStat statObject(String bucketName, String objectName) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        ObjectStat statObject = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
        return statObject;
    }

    /**文件访问路径*/
    @SneakyThrows
    public String getObjectUrl(String bucketName, String objectName) {
        boolean flag = bucketExists(bucketName);
        AssertUtils.assertTrue(flag,SystemCode.BIZ_EXCEPTION,"bucket不存在");
        return minioClient.getObjectUrl(bucketName, objectName);
    }

    public void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response) {
        try {
            InputStream file = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(originalName).build());
            String filename = new String(fileName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);
            if (StringUtils.isNotEmpty(originalName)) {
                filename = originalName;
            }
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            ServletOutputStream servletOutputStream = response.getOutputStream();
            int len;
            byte[] buffer = new byte[1024];
            while ((len = file.read(buffer)) > 0) {
                servletOutputStream.write(buffer, 0, len);
            }
            servletOutputStream.flush();
            file.close();
            servletOutputStream.close();
        } catch (ErrorResponseException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

完成手工

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值