>  기사  >  Java  >  SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

WBOY
WBOY앞으로
2023-05-11 12:16:051670검색

1. minio

MinIOKubernetes 배포를 기본적으로 지원하는 고성능 개체 스토리지 솔루션입니다. MinIOAmazon Web Services S3 호환 API를 제공하고 모든 핵심 S3 기능을 지원합니다. MinIO 是一个高性能的对象存储原生支持 Kubernetes 部署的解决方案。 MinIO 提供了一个 Amazon Web Services S3 兼容 API 并支持所有核心 S3 功能。

MinIO 对象存储使用 buckets 来组织对象。 存储桶类似于文件系统中的文件夹或目录,其中每个 桶可以容纳任意数量的对象。 MinIO 存储桶提供 与 AWS S3 存储桶相同的功能。

其中 MinIO 的优势有:

高性能:

MinIO是全球领先的对象存储先锋,在标准硬件上,读/写速度上高达183 GB / 秒171 GB / 秒

可扩展性:

MinIO利用了web缩放器的来之不易的知识,为对象存储带来了简单的存储缩放模型, 在 MinIO, 扩展从单个群集开始,该群集可以与其他MinIO群集联合以创建全局名称空间, 并在需要时可以跨越多个不同的数据中心。 通过添加更多集群可以扩展名称空间, 更多机架,直到实现目标。

云原生支持:

MinIO 是在过去4年的时间内从0开始打造的一款软件 ,符合一切原生云计算的架构和构建过程,并且包含最新的云计算的全新的技术和概念。 其中包括支持Kubernetes 、微服和多租户的的容器技术。使对象存储对于 Kubernetes更加友好。

源码开放与企业级支持:

MinIO 基于Apache V2 license 100% 开放源代码 。 这就意味着 MinIO的客户能够自动的、无限制、自由免费使用和集成MinIO、自由的创新和创造、 自由的去修改、自由的再次发行新的版本和软件. 确实, MinIO 强有力的支持和驱动了很多世界500强的企业。 此外,其部署的多样性和专业性提供了其他软件无法比拟的优势。

在实验开始前请确保安装完成了 minio

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

二、SpringBoot 使用 Minio 进行文件存储

首先新建一个 SpringBoot 项目,在 pom 中引入 minio 依赖:

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

在配置文件中,声明出 minio 的信息:

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

下面创建一个配置类,对 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;
    }
}

下面创建一个工具类 MinioTool 将常用的操作封装在工具类中:

@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();
    }

}

编写测试接口,进行测试:

@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();
    }

}

三、测试

测试上传文件:

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

如果使用 返回的 url 直接访问文件,可以发现返回权限不足:

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

这里需要改一下 BucketAccess Policy ,默认为 private,可以修改为 public 便无需认证,但安全性无法保证:

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

再次进行访问,文件就可以打开了:

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법

如果需要保持 private ,可以通过 MinioClient 进行下载,使用 download 测试接口下载文件:http://localhost:8080/file/download/20cab4e3979eba6003f95aca0dc75c63.jpg

MinIO 객체 스토리지는 버킷을 사용하여 객체를 정리합니다. 버킷은 파일 시스템의 폴더 또는 디렉터리와 유사하며, 각 버킷은 원하는 수의 객체를 보유할 수 있습니다. MinIO 버킷은 AWS S3 버킷과 동일한 기능을 제공합니다.

SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법MinIO의 장점은 다음과 같습니다.

🎜고성능: 🎜🎜MinIO는 표준 하드웨어에서 세계 최고의 개체 스토리지 선구자입니다. /쓰기 속도는 최대 183GB/초171GB/초입니다. 🎜🎜확장성:🎜🎜MinIO 스케일러에 대해 어렵게 얻은 지식을 활용하여 에서 객체 스토리지 스토리지 확장 모델을 단순하게 만듭니다. >MinIO, 확장은 단일 클러스터에서 시작됩니다. 이 클러스터는 다른 MinIO 클러스터와 연합하여 글로벌 네임스페이스를 생성할 수 있으며, 데이터 센터에 필요한 경우 여러 다른 클러스터로 확장될 수 있습니다. 목표가 달성될 때까지 더 많은 클러스터, 더 많은 랙을 추가하여 네임스페이스를 확장할 수 있습니다. 🎜🎜클라우드 네이티브 지원:🎜🎜MinIO는 지난 4년 동안 처음부터 새로 구축된 소프트웨어로 모든 네이티브 클라우드 컴퓨팅의 아키텍처 및 구성 프로세스를 준수하며 다음을 포함합니다. 최신의 새로운 클라우드 컴퓨팅 기술과 개념. 여기에는 Kubernetes, 마이크로서비스 및 멀티 테넌시를 지원하는 컨테이너 기술이 포함됩니다. 개체 저장소를 Kubernetes에 더 친숙하게 만드세요. 🎜🎜오픈 소스 및 엔터프라이즈 수준 지원:🎜🎜MinIOApache V2 라이선스 100% 오픈 소스를 기반으로 합니다. 이는 MinIO의 고객이 자동으로 MinIO를 자유롭게 사용 및 통합하고, 새로운 버전과 소프트웨어를 자유롭게 수정하고, 자유롭게 재배포할 수 있음을 의미합니다. MinIO는 많은 Fortune 500대 기업을 강력하게 지원하고 이끌어 왔습니다. 또한 배포의 다양성과 전문성은 다른 소프트웨어와 비교할 수 없는 이점을 제공합니다. 🎜🎜실험을 시작하기 전에 minio 설치가 완료되었는지 확인하세요: 🎜🎜SpringBoot는 파일 저장을 위해 Minio를 어떻게 사용합니까?🎜🎜2. SpringBoot는 파일 저장을 위해 Minio를 사용합니다🎜🎜먼저 새로운 SpringBoot 프로젝트를 생성하고 에 도입합니다. pom minio는 다음에 의존합니다: 🎜rrreee🎜구성 파일에서 minio의 정보를 선언합니다: 🎜rrreee🎜아래 구성 클래스를 생성하여 를 수행합니다 MinioClient 생성: 🎜rrreee🎜 아래 도구 클래스 MinioTool를 생성하고 도구 클래스에 일반적인 작업을 캡슐화합니다. 🎜rrreee🎜테스트 인터페이스 작성 및 테스트: 🎜rrreee🎜 3. 테스트 🎜 🎜 파일 업로드 테스트: 🎜🎜SpringBoot는 파일 저장을 위해 Minio를 어떻게 사용합니까? 🎜🎜반환된 URL을 사용하면 파일에 직접 접근할 때 반납 권한이 부족한 것을 확인할 수 있습니다: 🎜🎜SpringBoot 파일 저장을 위해 Minio를 사용하는 방법🎜🎜여기서 Bucket액세스 정책을 변경해야 합니다. 기본값은 private, public code>으로 수정 가능 인증은 필요하지 않지만 보안은 보장되지 않습니다: 🎜🎜<img src="https://img.php.cn/upload%20/article/000/887/227/168377857086128.jpg" alt="SpringBoot 파일 저장소와 함께 Minio를 사용하는 방법">🎜🎜<img src="https://img.php.cn/upload/article/000/%20887/227/168377857019765.jpg" alt="SpringBoot는 파일 저장을 위해 Minio를 어떻게 사용합니까?"> 🎜🎜<img src="https://img.php.cn/upload/article/000/887/227/168377857057222%20.jpg" alt="SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법">🎜🎜다시 방문하시면 파일을 열 수 있습니다: 🎜🎜<img src="https://img.php.cn/upload/article/000/%20887/227/168377857057448.jpg" alt="SpringBoot는 파일 저장을 위해 Minio를 어떻게 사용합니까?"> 🎜🎜<code>비공개를 유지해야 하는 경우 MinioClient를 통해 다운로드할 수 있습니다 다운로드 테스트 인터페이스를 사용하여 파일을 다운로드합니다: http://localhost: 8080/file/download/20cab4e3979eba6003f95aca0dc75c63.jpg🎜🎜🎜🎜

위 내용은 SpringBoot가 파일 저장을 위해 Minio를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제