Minio整合SpringBoot


POM:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.1.0</version>
</dependency>
yml文件配置(注意层级):
minio:
bucket: "桶名"
host: "http://192.168.1.123:5000"
url: "${minio.host}/${minio.bucket}/"
access-key: 用户名
secret-key: 密码
将MinioClient作为Bean加入容器管理
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Item;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile; import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List; import static io.minio.ErrorCode.NO_SUCH_KEY;
import static io.minio.http.Method.GET; @Component
public class MinioHelper { @Value(value = "${minio.bucket}")
private String bucket; @Value(value = "${minio.host}")
private String host; @Value(value = "${minio.url}")
private String url; @Value(value = "${minio.access-key}")
private String accessKey; @Value(value = "${minio.secret-key}")
private String secretKey; @Autowired
private MinioClient minioClient; @Bean
public MinioClient getMinioClient() {
MinioClient minioClient=MinioClient.builder()
.endpoint(host).credentials(accessKey,secretKey).build();
log.info("minioClient init success.");
return minioClient;
}
private final Logger log = LoggerFactory.getLogger(MinioHelper.class); /**
* 根据名字获得返回类型
* @param fileName
* @return
* @throws Exception
*/
public ObjectStat getStat(String fileName) throws Exception {
ObjectStat stat = minioClient.statObject(StatObjectArgs.builder()
.bucket(bucket).object(fileName).build());
return stat;
} /**
*上传文件到桶中
* @param multipartFile
* @param directory should be end with / or ""
* @return
* @throws IOException
* @throws InvalidKeyException
* @throws ErrorResponseException
* @throws IllegalArgumentException
* @throws InsufficientDataException
* @throws InternalException
* @throws InvalidBucketNameException
* @throws InvalidResponseException
* @throws NoSuchAlgorithmException
* @throws XmlParserException
* @throws RegionConflictException
* @throws ServerException
*/
public String putObject(MultipartFile multipartFile, String directory) throws
IOException, InvalidKeyException, ErrorResponseException, IllegalArgumentException,
InsufficientDataException, InternalException, InvalidBucketNameException, InvalidResponseException,
NoSuchAlgorithmException, XmlParserException, RegionConflictException, ServerException {
log.debug("start upload file .");
this.createBucket(minioClient, bucket);
String fileName = multipartFile.getOriginalFilename();
String rename = "";
log.debug("Upload File name is:" + fileName);
if (StringUtils.isNotEmpty(directory)) {
rename = renameFileVersion(directory + "/" + fileName, minioClient);
} else {
rename = renameFileVersion(fileName, minioClient);
}
try (InputStream inputStream = multipartFile.getInputStream()) {
minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(rename).
contentType(multipartFile.getContentType()).
stream(inputStream, multipartFile.getSize(), -1).build());
inputStream.close();
return rename;
}
} /**
* 获取文件的InputStream流对象
* @param fileUri format : directory/filename,filename must contains filetype,like xxx.pdf
* @throws IOException
* @throws InvalidKeyException
* @throws IllegalArgumentException
* @throws NoSuchAlgorithmException
*/
public InputStream getFileInputStream(String fileUri) throws
IOException, InvalidKeyException,IllegalArgumentException, NoSuchAlgorithmException {
log.debug("start get file IO.");
InputStream input=null;
try {
input=minioClient.getObject(GetObjectArgs.builder().bucket(bucket).object(fileUri).build());
} catch(MinioException e) {
log.debug("Error occurred: " + e.getMessage());
}
return input;
} /**
*在桶下创建文件夹,文件夹层级结构根据参数决定
* @param WotDir should be end with /
* @return
* @throws IOException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InternalException
* @throws XmlParserException
* @throws InvalidBucketNameException
* @throws ErrorResponseException
* @throws RegionConflictException
* @throws ServerException
*/
public String createDirectory(String WotDir) throws IOException, InvalidKeyException,
InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException,
InternalException, XmlParserException, InvalidBucketNameException,
ErrorResponseException, RegionConflictException, ServerException {
log.debug("start create directory.");
this.createBucket(minioClient,bucket);
minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(WotDir).stream(
new ByteArrayInputStream(new byte[] {}), 0, -1)
.build());
log.debug("Create a new Directory:"+WotDir);
return WotDir;
} /**
* 获取文件的下载url
* @param fileUri
* @return
* @throws IOException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws ServerException
* @throws InternalException
* @throws XmlParserException
* @throws InvalidBucketNameException
* @throws ErrorResponseException
* @throws RegionConflictException
* @throws InvalidExpiresRangeException
*/ public String getDownloadUrl(String fileUri) throws IOException, InvalidKeyException,
InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException,
ServerException,InternalException, XmlParserException, InvalidBucketNameException,
ErrorResponseException, RegionConflictException,
InvalidExpiresRangeException {
log.debug("start get url for download.");
this.createBucket(minioClient,bucket);
//Use Get Method
String fileurl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(this.bucket).object(fileUri).method(GET).build());
log.debug("You can download file through this url:"+fileurl);
return fileurl;
} /**
*该方法用于更新文档,
* @param multipartFile
* @param orderNum
* @return 是Minio中的Object名
* @throws IOException
* @throws InvalidKeyException
* @throws ErrorResponseException
* @throws IllegalArgumentException
* @throws InsufficientDataException
* @throws InternalException
* @throws InvalidBucketNameException
* @throws InvalidResponseException
* @throws NoSuchAlgorithmException
* @throws XmlParserException
* @throws RegionConflictException
* @throws ServerException
*/
public String uploadFileWithArgsForApp(MultipartFile multipartFile,String orderNum,String fileName) throws
IOException, InvalidKeyException, ErrorResponseException, IllegalArgumentException,
InsufficientDataException, InternalException, InvalidBucketNameException, InvalidResponseException,
NoSuchAlgorithmException, XmlParserException, RegionConflictException, ServerException {
log.debug("start upload file .");
this.createBucket(minioClient,bucket);
log.debug("Upload File name is:"+fileName);
String rename=orderNum+"/"+fileName;
try (InputStream inputStream = multipartFile.getInputStream()) {
minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(rename).
contentType(multipartFile.getContentType()).
stream(inputStream,multipartFile.getSize(),-1).build());
return rename;
}
} public String getloadUrl(String fileUri) throws IOException, InvalidKeyException,
InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException,
ServerException,InternalException, XmlParserException, InvalidBucketNameException,
ErrorResponseException, RegionConflictException,
InvalidExpiresRangeException {
log.debug("start get url for download.");
this.createBucket(minioClient,bucket);
//Use Get Method
String fileurl = minioClient.getObjectUrl(bucket,fileUri);
log.debug("You can download file through this url:"+fileurl);
return fileurl;
} /**
* 批量下载
* @param directory
* @return
* @throws IOException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws ServerException
* @throws InternalException
* @throws XmlParserException
* @throws InvalidBucketNameException
* @throws ErrorResponseException
* @throws InvalidExpiresRangeException
*/
public List<String> downLoadMore(String directory) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException, InvalidExpiresRangeException {
Iterable<Result<Item>> objs = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucket).prefix(directory).useUrlEncodingType(false).build());
List<String> list =new ArrayList<>();
for (Result<Item> result : objs) {
String objectName = null;
objectName = result.get().objectName();
ObjectStat statObject = minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build());
if (statObject != null && statObject.length() > 0) {
String fileurl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(this.bucket).object(statObject.name()).method(GET).build());
list.add(fileurl);
}
}
return list;
} /**
* 刪除文件
* @param fileUri
* @return
* @throws IOException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws ServerException
* @throws InternalException
* @throws XmlParserException
* @throws InvalidBucketNameException
* @throws ErrorResponseException
*/
public String removeFile(String fileUri) throws IOException, InvalidKeyException, InvalidResponseException,
InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException,
InvalidBucketNameException, ErrorResponseException {
log.debug("Start remove File :"+fileUri);
ObjectStat objectStat = minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(fileUri).build());
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(fileUri).build());
log.debug("File has been removed");
return fileUri; } /**
* 合并PDF
* @param files
* @param dir
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws IOException
* @throws InsufficientDataException
* @throws InternalException
* @throws InvalidResponseException
* @throws InvalidBucketNameException
* @throws XmlParserException
* @throws ServerException
* @throws ErrorResponseException
*/
public String mergeFile(List<String> files, String dir,String name) throws NoSuchAlgorithmException, InvalidKeyException, IOException, InsufficientDataException, InternalException, InvalidResponseException, InvalidBucketNameException, XmlParserException, ServerException, ErrorResponseException {
OutputStream outputStream = new ByteArrayOutputStream();
PDFMergerUtility merger = new PDFMergerUtility();
merger.setDestinationStream(outputStream);
for (String s:files
) {
InputStream in = this.getFileInputStream(s);
merger.addSource(in);//添加所有文件的输入流对象
}
merger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
log.debug("Merge File Stream success" );
ByteArrayOutputStream baos = (ByteArrayOutputStream) merger.getDestinationStream();
ByteArrayInputStream swapStream = new ByteArrayInputStream(baos.toByteArray());
MultipartFile multipartFile = new MockMultipartFile(name+".pdf", name+".pdf", "application/pdf", IOUtils.toByteArray(swapStream));
log.debug("Merge upload File has been create" );
String fileName = multipartFile.getOriginalFilename();
String rename = dir+"/"+fileName;
try (InputStream inputStream = multipartFile.getInputStream()) {
minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(rename).
contentType(multipartFile.getContentType()).
stream(inputStream, multipartFile.getSize(), -1).build());
inputStream.close();
return rename;
} } /**
* 重命名
* @param objectName
* @param minioClient
* @return
* @throws IOException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws ServerException
* @throws XmlParserException
* @throws InvalidBucketNameException
* @throws InternalException
* @throws ErrorResponseException
*/
private String renameFileVersion(String objectName,MinioClient minioClient) throws IOException, InvalidKeyException
, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, XmlParserException,
InvalidBucketNameException, InternalException, ErrorResponseException {
log.debug("start rename file.");
boolean flag =false;
int i=2;
StringBuffer temp = new StringBuffer(objectName.substring(0, objectName.length() - 4));
String result = objectName;
String sufix = objectName.substring(objectName.length() - 4);
String version = objectName.substring(objectName.length() - 7,objectName.length() - 4);
if(version.startsWith("_V")){//存在有版本号的,非初始版本
do{
try {
ObjectStat objectStat = minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(result).build());
temp=new StringBuffer(objectName.substring(0, objectName.length() - 7));
temp.append("_V"+i+sufix);
result = temp.toString();
i++;
flag = true;
} catch (ErrorResponseException e) {
if(e.errorResponse().errorCode().equals(NO_SUCH_KEY)){
flag=false;
}else throw e ;
}
}while (flag);
}else{
do{
try {
ObjectStat objectStat = minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(result).build());
//每次上传的版本不能低于上一个版本
//第一次上传不加版本号
//第二次上传为v2,依次叠加,后续上传规则变更,另作修改
if (i>2){
temp=new StringBuffer(objectName.substring(0, objectName.length() - 4));
}
temp.append("_V"+i+sufix);
result = temp.toString();
i++;
flag = true;
} catch (ErrorResponseException e) {
if(e.errorResponse().errorCode().equals(NO_SUCH_KEY)){
flag=false;
}else throw e ;
}
}while (flag);
} return result;
}
/*创建桶*/
private void createBucket(MinioClient minioClient,String bucket) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException, RegionConflictException {
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build())) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
log.debug("Create a new Bucket:"+bucket);
}else{
log.debug("Bucket has been exisit:"+bucket);
}
}
}

Minio整合SpringBoot的更多相关文章

  1. 整合springboot(app后台框架搭建四)

    springboot可以说是为了适用SOA服务出现,一方面,极大的简便了配置,加速了开发速度:第二方面,也是一个嵌入式的web服务,通过jar包运行就是一个web服务: 还有提供了很多metric,i ...

  2. 整合 springboot 和 swagger出问题

    整合 springboot 和 swagger ,出现报错, org.springframework.beans.factory.UnsatisfiedDependencyException: Err ...

  3. 【SpringBoot】搜索框架ElasticSearch介绍和整合SpringBoot

    ========================12章 搜索框架ElasticSearch介绍和整合SpringBoot ============================= 加入小D课堂技术交 ...

  4. netty-socketio整合springboot消息推送

    netty-socketio整合springboot消息推送 1.netty-socketio消息推送 1)在项目中常常涉及到消息推送的情况,消息推送要求的实时性,使用传统的方式已经不能满足需求了: ...

  5. 教你 Shiro 整合 SpringBoot,避开各种坑

    教你 Shiro 整合 SpringBoot,避开各种坑-----https://www.cnblogs.com/HowieYuan/p/9259638.html

  6. 基于 SpringBoot2.0+优雅整合 SpringBoot+Mybatis

    SpringBoot 整合 Mybatis 有两种常用的方式,一种就是我们常见的 xml 的方式 ,还有一种是全注解的方式.我觉得这两者没有谁比谁好,在 SQL 语句不太长的情况下,我觉得全注解的方式 ...

  7. 消息中间件——RabbitMQ(十)RabbitMQ整合SpringBoot实战!(全)

    前言 1. SpringBoot整合配置详解 publisher-confirms,实现一个监听器用于监听Broker端给我们返回的确认请求:RabbitTemplate.ConfirmCallbac ...

  8. Activiti7整合SpringBoot(十二)

    1 SpringBoot 整合 Activiti7 的配置 为了能够实现 SpringBoot 与 Activiti7 整合开发,首先我们要引入相关的依赖支持.所以,我们在工程的 pom.xml 文件 ...

  9. dubbo入门学习(三)-----dubbo整合springboot

    springboot节省了大量的精力去配置各种bean,因此通过一个简单的demo来整合springboot与dubbo 一.创建boot-user-service-provider 本篇博文基于上篇 ...

  10. liberty | 在IDEA整合Springboot与IBM liberty

    在IDEA整合Springboot与IBM liberty 简介 Liberty 是一款全新的轻量级应用服务器,它将用户的良好开发体验作为最主要的出发点.其主要特点和内容包括: 高模块化--该功能允许 ...

随机推荐

  1. flutter flutter_screenutil Looking up a deactivated widget's ancestor is unsafe.

    先强调一下,很多问题可以使用reStart更新试一下下!!!!! 使用flutter_screenutil 报错 Looking up a deactivated widget's ancestor ...

  2. 都用过@Autowired,但你知道它是怎么实现的吗

    前言 在使用Spring开发的时候,配置的方式主要有两种,一种是xml的方式,另外一种是 java config的方式.在使用的过程中java config,我们难免会与注解进行各种打交道,其中,我们 ...

  3. java入门与进阶-P1.3+P1.4

    准备一个java编程软件 eclipse官网: Enabling Open Innovation & Collaboration | The Eclipse Foundation 他是一个免费 ...

  4. 内存概述-java虚拟机的内存划分

    内存概述 内存是计算机中的重要原件,临时存储区域,作用是运行程序,我们编写写的程序是存放在硬盘中的,在硬盘中的程 序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存. Java虚拟机要运行程 ...

  5. 【学习笔记】C/C++ 设计模式 - 观察者模式

    前言 估计 2020 年写应用程序的机会比较多,之前一直在做嵌入式驱动程序和Android系统定制方面的工作,在应用程序方面积累的不是很多,因此迫切需要多学学应用编程这方面的知识. 之前在写小的应用程 ...

  6. Selenium中免登录的实现方法一option

    Selenium中免登录的实现方法一option 在selenium中有很多种可以实现网站的免登录,option就是其中的一种做法. 学员在VIP自动化课程中多有涉及. 1. 准备工作 打开一个网站( ...

  7. Seal 0.4 发布:软件供应链安全洞察更上一层楼!

    今天,我们很高兴宣布 Seal 0.4 已正式发布!在上一个版本中,Seal 完成了从单一产品到全链路平台的转变,通过全局视图帮助用户掌握软件开发生命周期各个环节的安全状况. 在 Seal 0.4 中 ...

  8. 限流器算法实现(JUC原子类使用实践)

    系列文章目录和关于我 一丶限流器存在的意义 在高并发系统中,出于系统保护角度考虑,通常会对流量进行限流. 限流*的目的是在遇到流量高峰期或者流量突增(流量尖刺)时,通过对流量速率进行限制,当达到限制速 ...

  9. keypoint数据结构

    公有属性 (float)angle:角度,表示关键点的方向,-1为初值. (int)class_id:当要对图片进行分类时,我们可以用class_id对每个特征点进行区分,未设定时为-1,需要靠自己设 ...

  10. 使用brew安装历史版本的几种方式

    背景 在 mac osx 下, 大部分的软件都是使用 homebrew 进行管理的, 可以方便的进行软件的安装,更新,删除等等, 大部分情况下 homebrew 的仓库只会存在一份最新的软件版本, 有 ...