微服务篇-深入了解 MinIO 文件服务器(你还在使用阿里云 0SS 对象存储图片服务?教你使用 MinIO 文件服务器:实现从部署到具体使用)

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 MinIO 文件服务器概述

        1.1 MinIO 使用 Docker 部署

        1.2 MinIO 控制台的使用

        2.0 使用 Java 操作 MinIO

        3.0 使用 minioClient 对象的方法

        3.1 判断桶是否存在

        3.2 创建桶

        3.3 删除桶

        3.4 删除桶内的对象

        3.5 获取 url

        3.6 上传文件

        3.7 下载文件

        3.8 获取所有桶

        3.9 获取所有桶名

        3.10 获取指定桶中的所有对象

        4.0 MinIO 工具类


        1.0 MinIO 文件服务器概述

        MinIO 是一个高性能的对象存储服务器,专门设计用来处理大规模的非结构化数据。它提供

与 Amazon S3(简单存储服务)兼容的 API,使得开发人员和运维团队能够轻松实现数据存储和

管理。以下是 MinIO 的一些关键特点和概述:

        1)高性能:MinIO 具有极高的吞吐量,能够支持大规模的并发请求,适用于需要快速处理大

量数据的应用场景,如机器学习和数据分析等。

        2)易于部署:MinIO 可以在多种环境中部署,包括本地服务器、虚拟机、容器(如 Docker

和 Kubernetes)以及云环境,以灵活适应不同的使用需求。

        3)兼容 S3 API:MinIO 采用与 S3 兼容的 API,这意味着用户可以使用现有的 S3 工具和软

件与 MinIO 进行交互,降低了迁移和集成的门槛。

        4)数据保护:MinIO 支持多种数据冗余和保护机制,包括纠删码(Erasure Coding),可以

在发生硬件故障时保护数据的完整性。

        5)安全性:MinIO 提供多种安全措施,包括身份验证、访问控制、TLS 加密等,确保数据在

传输和存储过程中的安全。

        6)企业级功能:MinIO 具备多租户支持、审计日志、生命周期管理等功能,适合企业和组织

使用。

        7)开源:MinIO 是一个开源项目,允许社区参与贡献和改进,同时也提供商业支持选项,适

合不同规模的企业使用。

MinIO 官网:MinIO | S3 Compatible Storage for AI

        在以往的项目中,用的比较多的是 OSS 服务有腾讯云、阿里云的存储服务,但是这些云存储

的服务大多数都是要收取一定的费用,一直积累起来也是一笔不小的费用。因此,自己部署一台

MinIO 文件服务器是一种不错的选择。

        1.1 MinIO 使用 Docker 部署

        1)执行以下命令进行部署:

docker run \-p 9000:9000 \-p 9001:9001 \--name minio \-v root\minio\data:/data \-e "MINIO_ROOT_USER=xbs12345" \-e "MINIO_ROOT_PASSWORD=xbs12345" \quay.io/minio/minio server /data --console-address ":9001"

        docker run:表示启动运行容器。

        -p:表示为容器绑定一个本地的端口。

        --name:表示为容器创建一个本地的名字。

        -v:表示将文件路径设置为容器使用持久卷位置。将数据保存到本地,使其能够在容器重启时保持持久化。

        -e:设置账号秘密。

        其中访问控制台的端口为:9001,api 的访问端口为:9000 。

        2)服务端部署完毕之后,通过控制台访问服务器:

访问 MinIO 控制台:

        http://自己的IP地址:9001

        1.2 MinIO 控制台的使用

        在对象存储服务里面,所有的文件都是以桶的形式来组织的。简单说,可以将桶看作是目

录,这个目录下有很多的文件或者文件夹,这和其它云存储服务基本一致。

首先需要创建桶:

        接着,设置桶名:

        桶这就创建好了:

        默认创建的存储桶,均为私有桶,无法被公开访问,需要设置成公开:

        通常而言,要将数据写入操作进行控制;而读操作,很多不涉及安全问题,希望能被互联网

公开访问,以便加快文件的访问速度。

        可以在存储桶里面配置,将数据读取权限设置为公开访问:

        测试上传图片:

        选择 Upload: 

        上传成功: 

        接着通过:http//自己的IP地址:9000/text/R-C (2).jpg 来访问,此时 "/text/R-C (2).jpg" 是桶

名与文件名的拼接。

        最后访问到已经上传的图片了:

        2.0 使用 Java 操作 MinIO

        1)首先引入依赖:

        <!-- 操作minio的java客户端--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.2</version></dependency>

        2)获取 API 访问凭证:

        生成密钥之后,需要记住这对密钥,最好保存起来。 

        3)在 application.yaml 中配置 MinIo:

#minio配置
spring:minio:access-key: xxxxxsecret-key: xxxxxurl: http://xxxxx:9000  #访问地址bucket-name: xbs

        将之前的密钥配置到该配置文件中,url 是 MinIO 的服务器地址,bucket-name 是表示对具

体某一个桶进行操作

        4)设置配置类:

import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Data
@Configuration
@ConfigurationProperties(prefix = "spring.minio")
public class MinioConfig {private String accessKey;private String secretKey;private String url;private String bucketName;@Beanpublic MinioClient minioClient(){return MinioClient.builder().endpoint(url).credentials(accessKey,secretKey).build();}
}

        通过 @ConfigurationProperties(prefix = "spring.minio") 注解,将配置文件中的参数映射

到当前类中的对应的属性中,通过 @Configuration 注解,将 minioClient 实体对象添加到

Spring IOC容器中。

        接下来,就可以使用 minioClient 实体对象中的方法,对文件进行操作,如上传文件到

MinIO服务器中、从 MinIO 服务器中下载文件、删除 MinIO 服务器中的文件等等。

        3.0 使用 minioClient 对象的方法

        3.1 判断桶是否存在

代码如下:

    @Autowiredprivate MinioClient minioClient;/*** 判断bucket是否存在,不存在就创建* @param bucketName bucket名称* @return 成功返回true,否则返回false*/public boolean exitBucket(String bucketName){try {//判断bucket是否存在BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();boolean isExist = minioClient.bucketExists(bucketExistsArgs);if (isExist){return true;}//不存在的话,则创建bucketMakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();minioClient.makeBucket(makeBucketArgs);return true;}catch (Exception e){e.printStackTrace();log.info("minio 连接失败");return false;}}

        根据桶名,来判断该桶是否存在 MinIO 中。

测试:

    @Testpublic void test() throws Exception {BucketExistsArgs build = BucketExistsArgs.builder().bucket("xbs").build();boolean b = minioClient.bucketExists(build);if (b){System.out.println("该桶存在");}}

执行结果:

        3.2 创建桶

代码如下:

    /*** 创建bucket* @param bucketName bucket名称* @return 成功创建返回true,否则返回false*/public boolean makeBucket(String bucketName){try {MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();minioClient.makeBucket(makeBucketArgs);}catch (Exception e){e.printStackTrace();log.info("桶创建失败");return false;}return true;}

        参数就只有一个,在 MinIO 服务器中创建 bucketName 的桶。

测试:

    @Testpublic void makeBucket() throws Exception {boolean xbs = minioUtils.makeBucket("hero");if (xbs){System.out.println("创建成功");return;}System.out.println("创建失败");}

执行结果:

        3.3 删除桶

代码如下:

    /*** 根据桶名删除* @param bucketName 桶名* @return 删除成功返回true,否则返回false*/public boolean removeBucket(String bucketName){try {RemoveBucketArgs removeBucketArgs = RemoveBucketArgs.builder().bucket(bucketName).build();minioClient.removeBucket(removeBucketArgs);}catch (Exception e){e.printStackTrace();log.info("桶删除失败");return false;}return true;}

        直接根据桶名来删除。

测试:

    @Testpublic void removeBucket() throws Exception {boolean hero = minioUtils.removeBucket("hero");if (hero){System.out.println("删除成功");return;}System.out.println("删除失败");}

执行结果:

        需要注意的是,当桶不为空,则删除桶失败。

测试:

        3.4 删除桶内的对象

代码如下:

    /*** 根据桶名、对象名来删除一个对象* @param bucketName 桶名* @param objectName 对象名* @return 删除成功返回true,否则返回false* @throws Exception*/public boolean removeObject(String bucketName, String objectName) throws Exception {try {RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build();minioClient.removeObject(removeObjectArgs);return true;}catch (Exception e) {e.printStackTrace();log.info("删除失败");return false;}}

        参数有两个,一个是桶名、另一个是对象名。根据桶名和对象名,可以确定删除的对象。这

里说的对象名,可以理解为文件名。

测试:

    @Testpublic void removeObject() throws Exception {boolean xbs = minioUtils.removeObject("text", "R-C (2).jpg");if (xbs){System.out.println("删除成功");return;}System.out.println("删除失败");}

执行结果:

        这就删除成功了。

        除了可以一个一个删除,也可以进行批量删除:

代码如下:

    /*** 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表** @param bucketName  存储桶名称* @param objectNames 含有要删除的多个object名称的迭代器对象* @return* eg:* List<DeleteObject> objects = new LinkedList<>();* objects.add(new DeleteObject("my-objectname1"));* objects.add(new DeleteObject("my-objectname2"));* objects.add(new DeleteObject("my-objectname3"));**/public List<String> removeObjects(String bucketName, List<DeleteObject> objectNames) throws Exception {List<String> deleteErrorNames = new ArrayList<>();try {RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket(bucketName).objects(objectNames).build();Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);for (Result<DeleteError> result : results) {DeleteError deleteError = result.get();deleteErrorNames.add(deleteError.objectName());}return deleteErrorNames;}catch (Exception e) {e.printStackTrace();log.info("删除失败");return null;}}

        3.5 获取 url

        当上传完照片之后,需要拿到可以访问到该照片的 url:

代码如下:

    /*** 获取url* @param bucketName 桶名* @param objectName 对象名* @param time 限制时间* @param unit 时间单位* @return 找不到返回null,找到返回对象的url*/public String getUrl(String bucketName, String objectName, int time, TimeUnit unit){try {GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(time, unit).build();return minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);}catch (Exception e){e.printStackTrace();log.info("获取url失败");return null;}}

        具体的参数有三个,桶名、对象名和设置过期时间。顾名思义,当超过了过期时间后,访问

图片失败。

测试:

    @Testpublic void getUrl() throws Exception{String xbs = minioUtils.getUrl("xbs", "v2-44a694ce65533da4b79b96a003acbbc7_r.jpg", 10, TimeUnit.SECONDS);System.out.println(xbs);}

执行结果:

        得到 url 后,可以直接访问:

        当超过 10 秒后,再次访问:

        时间过期了,就访问不了。

        3.6 上传文件

代码如下:

    /*** 上传文件* @param file 需要上传的文件* @param fileName 文件在桶中的命名* @param bucketName 需要上传的桶名* @return 上传成功返回true,否则返回false*/public boolean upload(MultipartFile file,String fileName,String bucketName){try {InputStream fileInputStream = file.getInputStream();PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName+file.getName().substring(file.getName().lastIndexOf("."))).stream(fileInputStream, file.getSize(), -1).contentType(file.getContentType()).build();minioClient.putObject(putObjectArgs);}catch (Exception e){e.printStackTrace();log.info("上传失败");return false;}return true;}

解析核心代码:

        1)首先,设置目标存储桶的名称为 bucketName。

        2)构建对象名称:fileName: 用户自定义的文件名前缀。

file.getName().substring(file.getName().lastIndexOf(".")): 获取原始文件的扩展名(从最后一个

点开始截取)。最终的对象名称是由 fileName 和文件扩展名拼接而成,确保上传后的文件名包含

正确的扩展名。

        3)fileInputStream: 文件的输入流,用于读取文件内容并上传到 MinIO。

file.getSize(): 文件的大小(以字节为单位),告诉 MinIO 文件的实际大小。

-1: 表示未知的分段大小(part size),MinIO 会根据文件大小自动处理分段上传。

        4)设置文件的内容类型(MIME 类型),例如 image/jpeg、application/pdf 等,这有助于

客户端正确解析下载的文件。

测试:

    @Testpublic void upload() throws Exception {// 创建一个 MockMultipartFile 实例来模拟图片文件String fileName = "1111.jpg";String contentType = "image/jpg";Path path = Paths.get("D:\\照片\\1111.jpg"); // 假设图片文件在目录下byte[] content = Files.readAllBytes(path);MultipartFile file = new MockMultipartFile(fileName, fileName, contentType, content);boolean xbs = minioUtils.upload(file, "4", "xbs");if (xbs){System.out.println("上传成功");}}

执行结果: 

        上传成功了。

        除了这种上传方式,还有一种是直接根据文件路径进行上传:

代码如下:

    /*** 上传文件* @param bucketName 桶名* @param objectName 对象名* @param fileName 文件路径* @return 上传成功返回true,否则返回false* @throws Exception*/public boolean uploadObject(String bucketName, String objectName, String fileName) throws Exception {try {UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build();minioClient.uploadObject(uploadObjectArgs);log.info("上传成功");return true;}catch (Exception e){e.printStackTrace();log.info("上传失败");return false;}}

        有三个简单的参数,桶名、需要上传文件的路径、上传文件之后在桶中的命名。

        3.7 下载文件

代码如下:

    /*** 下载文件* @param bucketName 桶名* @param objectName 目标下载对象* @return 下载成功返回true,否则返回false* @throws IOException*/public boolean download(String bucketName,String objectName) throws IOException {InputStream inputStream = null;OutputStream outputStream = null;try {GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(bucketName).object(objectName).build();inputStream = minioClient.getObject(getObjectArgs);File file = new File("D:/Download/" + objectName);outputStream = new FileOutputStream(file);IOUtils.copy(inputStream,outputStream);}catch (Exception e){e.printStackTrace();log.info("下载失败");return false;}finally {try {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}if (outputStream != null) {try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}} catch (Exception e) {e.printStackTrace();}}return true;}

        根据桶名、对象名来选中需要下载的文件,接着通过获取输入流之后拷贝到输出流中。从而

完成文件下载。

测试:

    @Testpublic void download() throws Exception{boolean xbs = minioUtils.download("xbs", "1.jpg");if (xbs){System.out.println("下载成功");return;}System.out.println("下载失败");}

执行结果:

        这就下载成功了。

        除了这种下载方式,还有另一个下载方式:

代码如下:

    /*** 下载文件* @param bucketName 桶名* @param objectName 对象名* @param fileName 下载到本地路径* @return* @throws Exception*/public boolean downloadObject(String bucketName, String objectName, String fileName) throws Exception {try {DownloadObjectArgs downloadObjectArgs = DownloadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build();minioClient.downloadObject(downloadObjectArgs);log.info("下载成功");return true;}catch (Exception e) {e.printStackTrace();log.info("下载失败");return false;}}

        直接给定三个参数:桶名、对象名、下载路径就可以完成下载文件。

        3.8 获取所有桶

代码如下:

    /*** 获取所有桶* @return 桶集合*/public List<Bucket> getAllBuckets(){List<Bucket> buckets = null;try {buckets = minioClient.listBuckets();}catch (Exception e){e.printStackTrace();log.info("获取桶失败");return null;}return buckets;}

测试:

    @Testpublic void getBucket(){List<Bucket> allBuckets = minioUtils.getAllBuckets();for (Bucket bucket : allBuckets) {System.out.println("bucket.name() = " + bucket.name());System.out.println("bucket.creationDate() = " + bucket.creationDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));}}

执行结果:

        3.9 获取所有桶名

代码如下:

    /*** 获取所有桶名* @return 桶名集合*/public List<String> getAllBucketNames(){List<Bucket> allBuckets = getAllBuckets();List<String> collect = null;if (CollUtil.isNotEmpty(allBuckets)){collect = allBuckets.stream().map(Bucket::name).collect(Collectors.toList());}return collect;}

测试:

    @Testpublic void getAllBucketNames() throws Exception {List<String> bucketNames = minioUtils.getAllBucketNames();if (CollUtils.isNotEmpty(bucketNames)) {System.out.println(bucketNames);}}

执行结果:

        3.10 获取指定桶中的所有对象

代码如下:

    /*** 获取桶内所有对象* @param bucketName 桶名* @return 返回对象集合*/public Iterable<Result<Item>> listObjects(String bucketName){try {ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder().bucket(bucketName).build();return minioClient.listObjects(listObjectsArgs);}catch (Exception e){e.printStackTrace();log.info("获取桶失败");return null;}}

        唯一的参数就是桶名,根据桶名来查询当前桶中的所有对象。

测试:

    @Testpublic void listObjects() throws Exception {Iterable<Result<io.minio.messages.Item>> listObjects = minioUtils.listObjects("xbs");for (Result<io.minio.messages.Item> itemResult : listObjects) {Item item = itemResult.get();System.out.println("item.getSize() = " + item.size());System.out.println("item.getObjectName() = " + item.objectName());}}

执行结果:

        4.0 MinIO 工具类

        通过以上的方法可以解决绝大部分的场景应用了,可以将这些的方法封装成一个 MinIO 的

工具类。

代码如下:

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import com.hmall.config.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;@Component
@Slf4j
//关于minio的工具
public class MinioUtils {@Autowiredprivate MinioConfig minioConfig;@Autowiredprivate MinioClient minioClient;/*** 判断bucket是否存在,不存在就创建* @param bucketName bucket名称* @return 成功返回true,否则返回false*/public boolean exitBucket(String bucketName){try {//判断bucket是否存在BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();boolean isExist = minioClient.bucketExists(bucketExistsArgs);if (isExist){return true;}//不存在的话,则创建bucketMakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();minioClient.makeBucket(makeBucketArgs);return true;}catch (Exception e){e.printStackTrace();log.info("minio 连接失败");return false;}}/*** 创建bucket* @param bucketName bucket名称* @return 成功创建返回true,否则返回false*/public boolean makeBucket(String bucketName){try {MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();minioClient.makeBucket(makeBucketArgs);}catch (Exception e){e.printStackTrace();log.info("桶创建失败");return false;}return true;}/*** 根据桶名删除* @param bucketName 桶名* @return 删除成功返回true,否则返回false*/public boolean removeBucket(String bucketName){try {RemoveBucketArgs removeBucketArgs = RemoveBucketArgs.builder().bucket(bucketName).build();minioClient.removeBucket(removeBucketArgs);}catch (Exception e){e.printStackTrace();log.info("桶删除失败");return false;}return true;}/*** 根据桶名、对象名来删除一个对象* @param bucketName 桶名* @param objectName 对象名* @return 删除成功返回true,否则返回false* @throws Exception*/public boolean removeObject(String bucketName, String objectName) throws Exception {try {RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build();minioClient.removeObject(removeObjectArgs);return true;}catch (Exception e) {e.printStackTrace();log.info("删除失败");return false;}}/*** 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表** @param bucketName  存储桶名称* @param objectNames 含有要删除的多个object名称的迭代器对象* @return* eg:* List<DeleteObject> objects = new LinkedList<>();* objects.add(new DeleteObject("my-objectname1"));* objects.add(new DeleteObject("my-objectname2"));* objects.add(new DeleteObject("my-objectname3"));**/public List<String> removeObjects(String bucketName, List<DeleteObject> objectNames) throws Exception {List<String> deleteErrorNames = new ArrayList<>();try {RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket(bucketName).objects(objectNames).build();Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);for (Result<DeleteError> result : results) {DeleteError deleteError = result.get();deleteErrorNames.add(deleteError.objectName());}return deleteErrorNames;}catch (Exception e) {e.printStackTrace();log.info("删除失败");return null;}}/*** 获取url* @param bucketName 桶名* @param objectName 对象名* @param time 限制时间* @param unit 时间单位* @return 找不到返回null,找到返回对象的url*/public String getUrl(String bucketName, String objectName, int time, TimeUnit unit){try {GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(time, unit).build();return minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);}catch (Exception e){e.printStackTrace();log.info("获取url失败");return null;}}/*** 上传文件* @param file 需要上传的文件* @param fileName 文件在桶中的命名* @param bucketName 需要上传的桶名* @return 上传成功返回true,否则返回false*/public boolean upload(MultipartFile file,String fileName,String bucketName){try {InputStream fileInputStream = file.getInputStream();PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName+file.getName().substring(file.getName().lastIndexOf("."))).stream(fileInputStream, file.getSize(), -1).contentType(file.getContentType()).build();minioClient.putObject(putObjectArgs);}catch (Exception e){e.printStackTrace();log.info("上传失败");return false;}return true;}/*** 上传文件* @param bucketName 桶名* @param objectName 对象名* @param fileName 文件路径* @return 上传成功返回true,否则返回false* @throws Exception*/public boolean uploadObject(String bucketName, String objectName, String fileName) throws Exception {try {UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build();minioClient.uploadObject(uploadObjectArgs);log.info("上传成功");return true;}catch (Exception e){e.printStackTrace();log.info("上传失败");return false;}}/*** 下载文件* @param bucketName 桶名* @param objectName 目标下载对象* @return 下载成功返回true,否则返回false* @throws IOException*/public boolean download(String bucketName,String objectName) throws IOException {InputStream inputStream = null;OutputStream outputStream = null;try {GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(bucketName).object(objectName).build();inputStream = minioClient.getObject(getObjectArgs);File file = new File("D:/Download/" + objectName);outputStream = new FileOutputStream(file);IOUtils.copy(inputStream,outputStream);}catch (Exception e){e.printStackTrace();log.info("下载失败");return false;}finally {try {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}if (outputStream != null) {try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}} catch (Exception e) {e.printStackTrace();}}return true;}/*** 下载文件* @param bucketName 桶名* @param objectName 对象名* @param fileName 下载到本地路径* @return* @throws Exception*/public boolean downloadObject(String bucketName, String objectName, String fileName) throws Exception {try {DownloadObjectArgs downloadObjectArgs = DownloadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build();minioClient.downloadObject(downloadObjectArgs);log.info("下载成功");return true;}catch (Exception e) {e.printStackTrace();log.info("下载失败");return false;}}/*** 获取所有桶* @return 桶集合*/public List<Bucket> getAllBuckets(){List<Bucket> buckets = null;try {buckets = minioClient.listBuckets();}catch (Exception e){e.printStackTrace();log.info("获取桶失败");return null;}return buckets;}/*** 获取所有桶名* @return 桶名集合*/public List<String> getAllBucketNames(){List<Bucket> allBuckets = getAllBuckets();List<String> collect = null;if (CollUtil.isNotEmpty(allBuckets)){collect = allBuckets.stream().map(Bucket::name).collect(Collectors.toList());}return collect;}/*** 获取桶内所有对象* @param bucketName 桶名* @return 返回对象集合*/public Iterable<Result<Item>> listObjects(String bucketName){try {ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder().bucket(bucketName).build();return minioClient.listObjects(listObjectsArgs);}catch (Exception e){e.printStackTrace();log.info("获取桶失败");return null;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/497346.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

logback之pattern详解以及源码分析

目录 &#xff08;一&#xff09;pattern关键字介绍 &#xff08;二&#xff09;源码分析 &#xff08;一&#xff09;pattern关键字介绍 %d或%date&#xff1a;表示日期&#xff0c;可配置格式化%d{yyyy-MM-dd HH:mm:ss} %r或%relative&#xff1a;也是日期&#xff0c;不过…

【期末复习】JavaEE(下)

1. MVC开发模式 1.1. 运行流程 1.2. SpringMVC 核心组件 1.3. 注解解释 2. ORM与MyBatis 2.1. ORM—对象关系映射 2.2. MyBatis 2.2.1. 创建步骤 会话是单例的&#xff0c;不能跨方法。&#xff08;单例的原因主要是从数据安全角度出发&#xff09; import org.apache.ibatis…

作业帮基于 Apache DolphinScheduler 3_0_0 的缺陷修复与优化

文|作业帮大数据团队&#xff08;阮文俊、孙建业&#xff09; 背 景 基于 Apache DolphinScheduler &#xff08;以下简称DolphinScheduler&#xff09;搭建的 UDA 任务调度平台有效支撑了公司的业务数据开发需求&#xff0c;处理着日均百万级别的任务量。 整个 UDA 的架构如…

电脑缺失sxs.dll文件要怎么解决?

一、文件丢失问题&#xff1a;以sxs.dll文件缺失为例 当你在运行某个程序时&#xff0c;如果系统提示“找不到sxs.dll文件”&#xff0c;这意味着你的系统中缺少了一个名为sxs.dll的动态链接库文件。sxs.dll文件通常与Microsoft的.NET Framework相关&#xff0c;是许多应用程序…

Web开发:ORM框架之使用Freesql的分表分页写法

一、自动分表&#xff08;高版本可用&#xff09; 特性写法 //假如是按月分表&#xff1a;[Table(Name "log_{yyyyMM}", AsTable "createtime2022-1-1(1 month)")]注意&#xff1a;①需包含log_202201这张表 ②递增规律是一个月一次&#xff0c;确保他们…

【数据结构与算法】单向链表

一、什么是链表 链表由一系列节点组成&#xff0c;每个节点都包含一个 data 域&#xff08;存放数据&#xff09;和一个 next 域&#xff08;指向下一节点&#xff09;。链表中的节点可以按照任意顺序存放在内存中&#xff0c;它们之间并不连续。每个节点都记录了下一个节点的地…

【ACCSS】2024年亚信安全云认证专家题库

文件包含&#xff1a; 亚信安全ACCSS认证2019年真题&#xff08;1&#xff09; 亚信安全ACCSS认证2019年真题&#xff08;2&#xff09; 亚信安全ACCSS认证2019年真题&#xff08;3&#xff09; 亚信安全ACCSS认证2020年真题&#xff08;1&#xff09; 亚信安全ACCSS认证2020年…

OpenCV-Python实战(10)——形态学

1、腐蚀 cv2.erode() 可以删除图像中的噪音点。 可以删除毛边。 分割图像&#xff08;当图像连接的不够紧密时&#xff09; 。 img cv2.erode(src*,kernel*,anchor*,iterations*,borderType*,borderValue*)img&#xff1a;目标图像。 src&#xff1a;原始图像。 kernel&…

用VBA将word文档处理成支持弹出式注释的epub文档可用的html内容

有一种epub文件&#xff0c;其中的注释以弹窗形式显示&#xff0c;如下图&#xff1a; 点击注释引用后&#xff0c;对应的注释内容会弹出在页面中显示&#xff0c;再次点击弹窗外的任意位置该弹窗即关闭&#xff0c;关闭后点击任意注释引用&#xff0c;对应的注释内容会弹窗显示…

Ngnix介绍、安装、实战及用法!!!

一、Nginx简介 1、Nginx概述 Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理服务器&#xff0c;特点是占有内存少&#xff0c;并发能力强&#xff0c;能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数 。 2、正向代理 正向代理&#xff1a;如果把局…

【超详细】Git的基本概念和基本使用方式

Git是程序开发中非常重要的工具&#xff0c;是一种分布式版本控制系统&#xff0c;可用于管理和追踪软件开发过程中的变化。那么关于Git的基本操作你知道吗&#xff1f;下面是Git的基本概念和使用方式的解释&#xff1a; 仓库&#xff08;Repository&#xff09;&#xff1a;Gi…

springboot503基于Sringboot+Vue个人驾校预约管理系统(论文+源码)_kaic

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装个人驾校预约管理系统软件来发挥其高效地信息处理的作用&am…

【Rust自学】7.4. use关键字 Pt.2 :重导入与换国内镜像源教程

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 7.4.1. 使用pub use重新导入名称 使用use将路径导入作用域内后。该名称在词作用域内是私有的。 以上一篇文章的代码为例&#xff1a; m…

Pandas03

Pandas01 Pandas02 文章目录 内容回顾1 排序和统计函数2 缺失值处理2.1 认识缺失值2.2 缺失值处理- 删除2.3 缺失值处理- 填充非时序数据时序数据 3 Pandas数据类型3.1 数值类型和字符串类型之间的转换3.2 日期时间类型3.3 日期时间索引 4 分组聚合4.1 分组聚合的API使用4.2 分…

平凉一窝丝:丝丝缕缕的舌尖风情

在平凉的美食版图中&#xff0c;食家巷一窝丝以其独特的工艺和诱人的口感&#xff0c;占据着重要的一席之地&#xff0c;成为了平凉人心目中的经典美食之一。从外观上看&#xff0c;平凉食家巷一窝丝如同一盘精心雕琢的金丝&#xff0c;根根细丝紧密盘绕&#xff0c;整齐而美观…

Wordly Wise 3000 国际背单词01 介绍 + 测词汇量

&#x1f4da; Wordly Wise 3000 国际背单词01 介绍 测词汇量 &#x1f31f; 大家好&#xff01;我们正式启动背Wordly Wise 3000单词&#xff0c;旨在利用国际资源和科学的学练方法&#xff0c;帮助大家更得效地坚持学练单词。我们将通过图文和Video等多种形式与大家分享经验…

C++进阶重点知识(一)|智能指针|右值|lambda|STL|正则表达式

目录 1智能指针1.shared_ptr1.1 shared_ptr的基本用法使用shared_ptr要注意的问题运用 2.unique_ptr独占的智能指针示例&#xff1a;管理动态内存 3.weak_ptr弱引用的智能指针weak_ptr的基本用法lock 的作用&#xff1a;weak_ptr返回this指针weak_ptr解决循环引用问题weak_ptr使…

计算机网络 (9)数据链路层

前言 计算机网络中的数据链路层&#xff08;Data Link Layer&#xff09;是OSI&#xff08;开放系统互连&#xff09;参考模型中的第二层&#xff0c;位于物理层和网络层之间。它在物理层提供的服务基础上&#xff0c;负责在相邻节点之间建立、维护和终止链路&#xff0c;确保数…

【Elasticsearch】DSL查询文档

目录 1.DSL查询文档 1.1.DSL查询分类 1.2.全文检索查询 1.2.1.使用场景 1.2.2.基本语法 1.2.3.示例 1.2.4.总结 1.3.精准查询 1.3.1.term查询 1.3.2.range查询 1.3.3.总结 1.4.地理坐标查询 1.4.1.矩形范围查询 1.4.2.附近查询 1.5.复合查询 1.5.1.相关性算分 …

国内独立开发者案例及免费送独立开发蓝图书

独立开发者在国内越来越受到关注&#xff0c;他们追求的是一种自由且自给自足的工作状态。 送这个&#xff1a; 少楠light&#xff08;Flomo、小报童、如果相机&#xff09;&#xff1a;他们是独立开发者的典范&#xff0c;不仅开发了多款产品&#xff0c;还坚信“剩者为王”…