Springboot实战:minio文件服务器 (附git源码下载)

Springboot-cli 开发脚手架系列



Minio简介

  • 高性能
    MinIO 是全球领先的对象存储先锋,目前在全世界有数百万的用户. 在标准硬件上,读/写速度上高达183 GB / 秒 和 171 GB / 秒。
    对象存储可以充当主存储层,以处理Spark、Presto、TensorFlow、H2O.ai等各种复杂工作负载以及成为Hadoop HDFS的替代品。
    MinIO用作云原生应用程序的主要存储,与传统对象存储相比,云原生应用程序需要更高的吞吐量和更低的延迟。而这些都是MinIO能够达成的性能指标。
  • 可扩展性
    MinIO利用了Web缩放器的来之不易的知识,为对象存储带来了简单的缩放模型。 这是我们坚定的理念 “简单可扩展.” 在 MinIO, 扩展从单个群集开始,该群集可以与其他MinIO群集联合以创建全局名称空间, 并在需要时可以跨越多个不同的数据中心。 通过添加更多集群可以扩展名称空间, 更多机架,直到实现目标。
  • 云的原生支持
    MinIO 是在过去4年的时间内从0开始打造的一款软件 ,符合一切原生云计算的架构和构建过程,并且包含最新的云计算的全新的技术和概念。 其中包括支持Kubernetes 、微服和多租户的的容器技术。使对象存储对于 Kubernetes更加友好。

关于minio的介绍就到这,接下来我们进行实战演示。

1. 环境配置

  • pom.xml
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 <!--     huTool工具包  -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.22</version>
        </dependency>
  <!-- https://mvnrepository.com/artifact/io.minio/minio -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.3.9</version>
            <!--           避免依赖冲突 -->
            <exclusions>
                <exclusion>
                    <artifactId>okhttp</artifactId>
                    <groupId>com.squareup.okhttp3</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.0</version>
        </dependency>
  • yml配置
server:
  port: 9999

minio:
  endpoint: http://localhost:20000
  accessKey: admin
  secretKey: 12345678
  secure: false
  bucketName: test

2. 配置MinioClient

  • MinioProperties
@Data
@Component
@ConfigurationProperties(prefix = MinioProperties.PRE)
public class MinioProperties {

    public static final String PRE = "minio";
    /**
     * endPoint是一个URL,域名,IPv4或者IPv6地址
     */
    private String endpoint;

    /**
     * accessKey类似于用户ID,用于唯一标识你的账户
     */
    private String accessKey;

    /**
     * secretKey是你账户的密码
     */
    private String secretKey;

    /**
     * 如果是true,则用的是https而不是http,默认值是true
     */
    private Boolean secure;

    /**
     * 默认存储桶
     */
    private String bucketName;
    
    @Bean
    public MinioClient getMinioClient() throws Exception {
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }
}

3. 文件上传下载

  • MinioHandler.java
@Component
@Slf4j
@RequiredArgsConstructor
public class MinioHandler {

    private final MinioClient minioClient;

    private final MinioProperties minioProperties;

    /**
     * 判断bucket是否存在
     *
     * @param name 存储桶名称
     */
    public boolean existBucket(String name) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 创建存储bucket
     *
     * @param bucketName 存储bucket名称
     */
    public boolean createdBucket(String bucketName) throws Exception {
        if (!this.existBucket(bucketName)) {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
            return true;
        }
        return false;
    }

    /**
     * 删除存储bucket
     *
     * @param bucketName 存储bucket名称
     */
    public boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * description: 上传文件
     *
     * @param file 文件
     * @return: List<String> s
     */
    public String saveFile(MultipartFile file) throws Exception {
        if (Objects.isNull(file)) {
            return "";
        }
        String fileName;
        try {
            fileName = file.getOriginalFilename();
            InputStream in = file.getInputStream();
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())
                    .object(fileName)
                    .stream(in, in.available(), -1)
                    .contentType(file.getContentType())
                    .build()
            );
        } finally {
            Optional.ofNullable(in).ifPresent(inputStream -> {
                try {
                    inputStream.close();
                } catch (IOException ignored) {
                }
            });
        }
        log.info("文件保存成功,文件名:{},类型:{}", fileName, file.getContentType());
        return fileName;
    }

    /**
     * description: 上传文件
     *
     * @param files 文件
     * @return: List<String> s
     */
    public List<String> saveFile(MultipartFile[] files) throws Exception {
        List<String> names = new ArrayList<>(files.length);
        for (MultipartFile file : files) {
            names.add(this.saveFile(file));
        }
        return names;
    }

    /**
     * 获取文件
     */
    public InputStream getFile(String fileName) throws Exception {
        return minioClient.getObject(GetObjectArgs.builder().bucket(minioProperties.getBucketName()).object(fileName).build());
    }

    /**
     * description: 下载文件
     *
     * @param fileName 文件名
     * @return: org.springframework.http.ResponseEntity<byte [ ]>
     */
    public ResponseEntity<byte[]> download(String fileName) {
        return this.download(fileName, MediaType.APPLICATION_OCTET_STREAM);
    }

    /**
     * description: 下载文件
     *
     * @param fileName 文件名
     * @return: org.springframework.http.ResponseEntity<byte [ ]>
     */
    public ResponseEntity<byte[]> download(String fileName, MediaType mediaType) {
        ResponseEntity<byte[]> responseEntity = null;
        InputStream in = null;
        try {
            in = this.getFile(fileName);
            // 封装返回值
            byte[] bytes = IoUtil.readBytes(in);
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
            headers.setContentLength(bytes.length);
            headers.setContentType(mediaType);
            headers.setAccessControlExposeHeaders(List.of("*"));
            responseEntity = new ResponseEntity<>(bytes, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Optional.ofNullable(in).ifPresent(
                    i -> {
                        try {
                            i.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
            );
        }

        return responseEntity;
    }

    /**
     * 查看文件对象
     *
     * @param bucketName 存储bucket名称
     */
    public void listObjects(String bucketName) {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).build());
        try {
            for (Result<Item> result : results) {
                Item item = result.get();
                String s = item.objectName();
                long size = item.size();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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


}

4. web实战演示

  • 编写MinioController.java文件服务api
@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("minio")
public class MinioController {

    private final MinioHandler minioHandler;

    /**
     * 创建存储桶
     */
    @GetMapping("/createdBucket")
    public boolean createdBucket(String bucketName) throws Exception {
        return minioHandler.createdBucket(bucketName);
    }

    /**
     * 创建存储桶
     */
    @GetMapping("/removeBucket")
    public boolean removeBucket(String bucketName) {
        return minioHandler.removeBucket(bucketName);
    }

    /**
     * 上传文件
     */
    @PostMapping("upload")
    public List<String> saveFile(MultipartFile[] files) throws Exception {
        return minioHandler.saveFile(files);
    }

    /**
     * 下载文件
     */
    @GetMapping(value = "download")
    public ResponseEntity<byte[]> download(String filename) {
        return minioHandler.download(filename);
    }

    /**
     * 以图片形式返回
     */
    @GetMapping("get/image")
    public ResponseEntity<byte[]> getImage(String filename) {
        return minioHandler.download(filename, MediaType.IMAGE_JPEG);
    }
}
  • postman测试工具为例子测试
  • 文件上传127.0.0.1:9999/minio/upload
    在这里插入图片描述
  • 文件下载``
    在这里插入图片描述
  • 以图片的形式获取

在这里插入图片描述

6. 源码分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈小定

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值