Home >Java >javaTutorial >How SpringBoot uses Minio for file storage

How SpringBoot uses Minio for file storage

WBOY
WBOYforward
2023-05-11 12:16:051682browse

1. minio

MinIO is a high-performance object storage solution that natively supports Kubernetes deployment. MinIO provides an Amazon Web Services S3 that is API compatible and supports all core S3 functionality.

MinIO Object storage uses buckets to organize objects. Buckets are similar to folders or directories in a file system, where each bucket can hold any number of objects. MinIO buckets provide the same functionality as AWS S3 buckets.

The advantages of MinIO are:

High performance:

MinIO is the world’s leading Pioneer in object storage, with read/write speeds of up to 183 GB/second and 171 GB/second on standard hardware.

Scalability:

MinIO leverages the hard-won knowledge of web scalers to provide the best solution for object storage Bringing a simple storage scaling model, in MinIO, scaling starts from a single cluster that can be federated with other MinIO clusters to create a global namespace, and can be spanned when needed Multiple different data centers. The namespace can be expanded by adding more clusters, more racks, until the goal is achieved.

Cloud native support:

MinIO is a software built from scratch in the past 4 years and is in line with all native clouds Computing architecture and construction process, and includes the latest cloud computing new technologies and concepts. This includes container technology that supports Kubernetes, microservices and multi-tenancy. Make object storage more friendly to Kubernetes.

Open source code and enterprise-level support:

MinIO Based on Apache V2 license 100% open source code. This means that customers of MinIO can automatically, unrestrictedly and freely use and integrate MinIO, freely innovate and create, freely modify, and freely re-release new ones. Version and software. Indeed, MinIO has strongly supported and driven many Fortune 500 companies. In addition, the diversity and professionalism of its deployment provide advantages that other software cannot match.

Please make sure the installation is complete before starting the experimentminio:

How SpringBoot uses Minio for file storage

##2. SpringBoot uses Minio for file storage

First create a new

SpringBoot project and introduce minio dependencies in pom:

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

In the configuration file, declare

Information about minio:

minio:
  url: http://192.168.40.169:9000   # minio配置的地址,端口9000,注意不是控制台的端口
  accessKey: minioadmin   # 账号
  secretKey: minioadmin   # 密码
  bucketName: test-bucket  # MinIO桶名字

Create a configuration class below to create

MinioClient:

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
    /**
     * 服务地址
     */
    private String url;
 
    /**
     * 用户名
     */
    private String accessKey;
 
    /**
     * 密码
     */
    private String secretKey;
 
    /**
     * 存储桶名称
     */
    private String bucketName;

    @Bean
    public MinioClient getMinioClient() throws Exception {
        MinioClient minioClient = MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
        //判断桶是否存在,不存在则新建
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())){
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        }
        return minioClient;
    }
}

Create a tool class below

MinioTool Encapsulate commonly used operations in tool classes:

@Component
public class MinioTool {
    
    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig minioConfig;
 
    /**
     * 查看存储bucket是否存在
     *
     * @param bucketName 存储bucket
     * @return boolean
     */
    public Boolean bucketExists(String bucketName) {
        Boolean found;
        try {
            found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return found;
    }
 
    /**
     * 创建存储bucket
     *
     * @param bucketName 存储bucket名称
     * @return Boolean
     */
    public Boolean makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
 
    /**
     * 删除存储bucket
     *
     * @param bucketName 存储bucket名称
     * @return Boolean
     */
    public Boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 查看文件对象
     *
     * @param bucketName 存储bucket名称
     * @return 存储bucket内文件对象信息
     */
    public Iterable<Result<Item>> listObjects(String bucketName) {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).build());
        return results;
    }

    /**
     * 批量删除文件对象
     *
     * @param bucketName 存储bucket名称
     * @param objects    对象名称集合
     */
    public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
        List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
        return results;
    }


    /**
     * 文件上传
     * 文件名称相同会覆盖
     * @param file       文件
     * @return Boolean
     */
    public Boolean upload(MultipartFile file, String fileName) {
        try {
            if (!bucketExists(minioConfig.getBucketName())) {
                makeBucket(minioConfig.getBucketName());
            }
            PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
            minioClient.putObject(objectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
 
    /**
     * 文件下载
     *
     * @param fileName   文件名称
     * @param res        response
     * @return Boolean
     */
    public void download(String fileName, HttpServletResponse res) {
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(minioConfig.getBucketName())
                .object(fileName).build();
        try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
            byte[] buf = new byte[1024];
            int len;
            try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
                while ((len = response.read(buf)) != -1) {
                    os.write(buf, 0, len);
                }
                os.flush();
                byte[] bytes = os.toByteArray();
                res.setCharacterEncoding("utf-8");
                //设置强制下载不打开
                res.setContentType("application/force-download");
                res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
                try (ServletOutputStream stream = res.getOutputStream()) {
                    stream.write(bytes);
                    stream.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getFileUrl(String fileName){
        return StringFormatter.concat(minioConfig.getUrl(), "/", minioConfig.getBucketName(), "/", fileName).getValue();
    }

}

Write test interfaces and test:

@Component
public class MinioTool {
    
    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig minioConfig;
 
    /**
     * 查看存储bucket是否存在
     *
     * @param bucketName 存储bucket
     * @return boolean
     */
    public Boolean bucketExists(String bucketName) {
        Boolean found;
        try {
            found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return found;
    }
 
    /**
     * 创建存储bucket
     *
     * @param bucketName 存储bucket名称
     * @return Boolean
     */
    public Boolean makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
 
    /**
     * 删除存储bucket
     *
     * @param bucketName 存储bucket名称
     * @return Boolean
     */
    public Boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 查看文件对象
     *
     * @param bucketName 存储bucket名称
     * @return 存储bucket内文件对象信息
     */
    public Iterable<Result<Item>> listObjects(String bucketName) {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).build());
        return results;
    }

    /**
     * 批量删除文件对象
     *
     * @param bucketName 存储bucket名称
     * @param objects    对象名称集合
     */
    public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
        List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
        return results;
    }


    /**
     * 文件上传
     * 文件名称相同会覆盖
     * @param file       文件
     * @return Boolean
     */
    public Boolean upload(MultipartFile file, String fileName) {
        try {
            if (!bucketExists(minioConfig.getBucketName())) {
                makeBucket(minioConfig.getBucketName());
            }
            PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
            minioClient.putObject(objectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
 
    /**
     * 文件下载
     *
     * @param fileName   文件名称
     * @param res        response
     * @return Boolean
     */
    public void download(String fileName, HttpServletResponse res) {
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(minioConfig.getBucketName())
                .object(fileName).build();
        try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
            byte[] buf = new byte[1024];
            int len;
            try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
                while ((len = response.read(buf)) != -1) {
                    os.write(buf, 0, len);
                }
                os.flush();
                byte[] bytes = os.toByteArray();
                res.setCharacterEncoding("utf-8");
                //设置强制下载不打开
                res.setContentType("application/force-download");
                res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
                try (ServletOutputStream stream = res.getOutputStream()) {
                    stream.write(bytes);
                    stream.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getFileUrl(String fileName){
        return StringFormatter.concat(minioConfig.getUrl(), "/", minioConfig.getBucketName(), "/", fileName).getValue();
    }

}

3. Test

Test upload files:

How SpringBoot uses Minio for file storage

If you use the returned url to directly access the file, you can find that the return permission is insufficient:

How SpringBoot uses Minio for file storage

You need to change it here

Bucket The Access Policy defaults to private and can be modified to public without authentication, but security cannot be guaranteed:

How SpringBoot uses Minio for file storage

How SpringBoot uses Minio for file storage

How SpringBoot uses Minio for file storage

Access again and the file can be opened:

How SpringBoot uses Minio for file storage

If necessary Keep

private, you can download through MinioClient, use the download test interface to download the file: http://localhost:8080/file/download/20cab4e3979eba6003f95aca0dc75c63 .jpg

How SpringBoot uses Minio for file storage

The above is the detailed content of How SpringBoot uses Minio for file storage. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete