微服务篇-深入了解 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.mzph.cn/bicheng/65465.shtml

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

相关文章

第一个C++程序|cin和cout|命名空间

第一个C程序 基础程序 使用DevC5.4.0 写一个C程序 在屏幕上打印hello world #include <iostream> using namespace std;int main() {cout << "hello world" << endl;return 0; } 运行这个C程序 F9->编译 F10->运行 F11->编译运行 mai…

强化特种作业管理,筑牢安全生产防线

在各类生产经营活动中&#xff0c;特种作业由于其操作的特殊性和高风险性&#xff0c;一直是安全生产管理的重点领域。有效的特种作业管理体系涵盖多个关键方面&#xff0c;从作业人员的资质把控到安全设施的配备维护&#xff0c;再到特种设备的精细管理以及作业流程的严格规范…

iOS 苹果开发者账号: 查看和添加设备UUID 及设备数量

参考链接&#xff1a;苹果开发者账号下添加新设备UUID - 简书 如果要添加新设备到 Profiles 证书里&#xff1a; 1.登录开发者中心 Sign In - Apple 2.找到证书设置&#xff1a; Certificate&#xff0c;Identifiers&Profiles > Profiles > 选择对应证书 edit &g…

如何让Tplink路由器自身的IP网段 与交换机和电脑的IP网段 保持一致?

问题分析&#xff1a; 正常情况下&#xff0c;我的需求是&#xff1a;电脑又能上网&#xff0c;又需要与路由器处于同一局域网下&#xff08;串流Pico4 VR眼镜&#xff09;&#xff0c;所以&#xff0c;我是这么连接 交换机、路由器、电脑 的&#xff1a; 此时&#xff0c;登录…

(南京观海微电子)——GH7009开机黑屏案例分析

一、 现象描述&#xff1a; 不良现象: LVDS模组&#xff0c;开机大概2秒后就黑屏。 二、问题分析 等主机进入Kernel 后做以下测试&#xff1a; 1、手动reset LCM 后 可以显示正常&#xff1b; 总结&#xff1a; 1&#xff09;uboot 部分HS 太窄&#xff0c;仅有4个clk宽度&am…

第10章 初等数论

2024年12月27日一稿&#xff08;P341&#xff09; 2024年12月28日二稿 2024年12月29日三稿 当命运这扇大门向你打开的时候&#xff0c;不要犹豫和害怕&#xff0c;一直往前跑就是了&#xff01; 10.1 素数 这里写错了&#xff0c;不能整除应该表示为 10.2 最大公约数与最小公…

XXE漏洞 黑盒测试 白盒测试 有无回显问题

前言 什么是XXE&#xff08;xml外部实体注入漏洞&#xff09;&#xff1f; 就是网站以xml传输数据 的时候我们截取他的传输流进行修改&#xff08;网站没有对我们的输入进行过滤&#xff09; 添加恶意代码 导致数据传输到后台 后台解析xml形式 导致恶意代码被执行 几种常见的…

yolov5 yolov6 yolov7 yolov8 yolov9目标检测、目标分类 目标切割 性能对比

文章目录 YOLOv1-YOLOv8之间的对比如下表所示&#xff1a;一、YOLO算法的核心思想1. YOLO系列算法的步骤2. Backbone、Neck和Head 二、YOLO系列的算法1.1 模型介绍1.2 网络结构1.3 实现细节1.4 性能表现 2. YOLOv2&#xff08;2016&#xff09;2.1 改进部分2.2 网络结构 3. YOL…

jdk版本介绍

1.JDK版本编号 • 主版本号&#xff1a;表示JDK的主要版本&#xff0c;如JDK 8、JDK 11中的8和11。主版本号的提升通常意味着引入了重大的新特性或变更。 • 次版本号&#xff1a;在主版本号之后&#xff0c;有时会跟随一个或多个次版本号&#xff08;如JDK 11.0.2中的0.2&…

低代码开源项目Joget的研究——基本概念和Joget7社区版应用

大纲 1. 基本概念1.1 Form1.1.1 Form1.1.1.1 概述1.1.1.2 主要特点和用途1.1.1.3 创建和使用 Form1.1.1.4 示例 1.1.2 Section1.1.2.1 概述1.1.2.2 主要特点和用途1.1.2.3 示例 1.1.3 Column1.1.4 Field1.1.5 示例 1.2 Datalist1.2.1 Datalist1.2.1.1 主要特点和用途1.2.1.2 创…

【LeetCode 04】 209. 长度最小的子数组

暴力解法&#xff1a; 测试通过✅提交超时❌ class Solution {public int minSubArrayLen(int target, int[] nums) {//暴力解法int sum0;int subLength0;int resultInteger.MAX_VALUE;int lennums.length;for(int i0;i<len;i){//起始位置sum0;for(int ji;j<len;j){//终…

【已解决】图片png转ico格式

起因&#xff1a; pyinstaller 打包时需要 ico 格式图片&#xff0c;但是通常手上只有png格式的图片&#xff0c;为了将png转为ico&#xff0c;直接改后缀会报错“struct.error: unpack requires a buffer of 16 bytes”&#xff0c;我就上网搜了一下&#xff0c;发现都是一些…

AMD | GPU | 深度学习 | 如何使用

问题&#xff1a;我在复现代码的时候&#xff0c;发现自己只拥有AMD的GPU&#xff0c;对于一个硬件小白来说&#xff0c;怎么办呢&#xff1f;我想看看怎么使用&#xff1b;解决&#xff1a; 首先要安装支持AMD的GPU的pytorch&#xff0c;pytorch&#xff1b; 使程序在安装了支…

Blender高效优化工作流程快捷小功能插件 Haggis Tools V1.1.5

Haggis Tools V1.1.5 是一款专为Blender设计的插件&#xff0c;旨在优化工作流程、减少单调和重复的任务&#xff0c;从而为艺术家节省时间。这款插件适用于多个版本的Blender&#xff0c;能够有效提升工作效率。 Blender插件特点&#xff1a; 工作流程优化&#xff1a;专门设…

数据采集背后的效率革命:如何优化你的爬虫性能

在爬虫技术日益发展的今天&#xff0c;性能优化成为提升数据采集效率的关键。面对日益复杂的网页结构和庞大的数据量&#xff0c;高效的爬虫能够显著降低运行时间和资源成本。本文将围绕爬虫性能优化的核心方法展开讨论&#xff0c;并通过实例对比多进程、多线程以及普通爬取的…

OpenHarmony-5.PM 子系统(2)

电池服务组件OpenHarmony-4.1-Release 1.电池服务组件 Battery Manager 提供了电池信息查询的接口&#xff0c;同时开发者也可以通过公共事件监听电池状态和充放电状态的变化。电池服务组件提供如下功能&#xff1a; 电池信息查询。充放电状态查询。关机充电。 电池服务组件架…

测试冰淇淋模型

测试领域的冰淇淋模型&#xff08;Ice Cream Cone Model&#xff09;是一个相对于传统的测试金字塔模型的反转&#xff0c;是一种与经典金字塔模型相对的测试策略。在这种模型中&#xff0c;测试的分布和重点与传统金字塔模型相反。以下是冰淇淋模型的主要特点和原因&#xff1…

短视频矩阵账号管理技术源码搭建详解,支持OEM

一、引言 在短视频矩阵系统中&#xff0c;账号管理是至关重要的一环&#xff0c;它涉及到多平台账号的接入、用户信息的安全存储与高效管理、权限的精准控制以及账号数据的同步与更新等关键功能。一个健壮、灵活且安全的账号管理技术架构&#xff0c;能够为整个短视频矩阵系统的…

【驱动开发】设备分类、设备号申请和注销,注册和移除字符设备,以及一个基本的内核驱动程序框架代码

一、Linux内核对设备的分类 Linux的文件种类 序号符号类型文件内容文件名原信息1-普通文件√√√2d目录文件√√√3p管道文件√√4s本地socket文件√√5l链接文件软链接有;硬链接相当于别名√√6c字符设备√√7b块设备√√设备类型 Linux内核按驱动程序实现模型框架的不同,…

黑马Java面试教程_P2_MySQL

系列博客目录 文章目录 系列博客目录前言1. 优化1.1 MySQL中&#xff0c;如何定位慢查询&#xff1f;面试文稿 1.2 面试官接着问&#xff1a;那这个SQL语句执行很慢,如何分析 ( 如何优化&#xff09;呢?面试文稿 1.3 了解过索引吗?(什么是索引)1.4 继续问 索引的底层数据结构…