1.配置minio MinioAutoConfiguration 类
@AllArgsConstructor@EnableConfigurationProperties({MinioProperties.class})public class MinioAutoConfiguration { private final MinioProperties properties; @Bean @ConditionalOnMissingBean(MinioTemplate.class) @ConditionalOnProperty(name = "amc.minio.url") MinioTemplate minioTemplate() { return new MinioTemplate( properties.getUrl(), properties.getAccessKey(), properties.getSecretKey() ); }}
2.属性类
@Data@ConfigurationProperties(prefix = "amc.minio")public class MinioProperties { /** * minio 服务地址 http://ip:port */ private String url; /** * 用户名 */ private String accessKey; /** * 密码 */ private String secretKey;}
3.创建minioTemplate工具类
package com.amc.minio.entity;import cn.hutool.core.util.StrUtil;import cn.hutool.core.util.URLUtil;import io.minio.*;import io.minio.errors.*;import io.minio.http.Method;import io.minio.messages.Bucket;import io.minio.messages.Item;import lombok.RequiredArgsConstructor;import lombok.SneakyThrows;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.InitializingBean;import org.springframework.util.Assert;import java.io.IOException;import java.io.InputStream;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Optional;/** * minio 交互类 * @author Administrator */@RequiredArgsConstructor@Slf4jpublic class MinioTemplate implements InitializingBean { private final String endpoint; private final String accessKey; private final String secretKey; private MinioClient client; /** * 创建bucket * * @param bucketName bucket名称 */ @SneakyThrows public void createBucket(String bucketName) { if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) { client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } } /** * 合并分片文件成对象文件 * * @param chunkBucKetName 分片文件所在存储桶名称 * @param composeBucketName 合并后的对象文件存储的存储桶名称 * @param chunkNames 分片文件名称集合 * @param objectName 合并后的对象文件名称 * @return true/false */ @SneakyThrows public boolean composeObject(String chunkBucKetName, String composeBucketName, List<String> chunkNames, String objectName) { if (null == chunkBucKetName) { chunkBucKetName = "chunk"; } List<ComposeSource> sourceObjectList = new ArrayList<>(chunkNames.size()); for (String chunk : chunkNames) { sourceObjectList.add( ComposeSource.builder() .bucket(chunkBucKetName) .object(chunk) .build() ); } client.composeObject( ComposeObjectArgs.builder() .bucket(composeBucketName) .object(objectName) .sources(sourceObjectList) .build() ); return true; } /** * 根据md5获取所有分片文件名称(minio的文件名称 = 文件path) * @param bucketName 桶(文件夹)名称 * @param prefix 前缀 * @return List<String> */ @SneakyThrows public List<String> listObjectNames(String bucketName, String prefix) { List<String> chunkPaths = new ArrayList<>(); ListObjectsArgs listObjectsArgs; if (StrUtil.isBlank(prefix)) { listObjectsArgs = ListObjectsArgs.builder() .bucket(bucketName) .recursive(true) .build(); } else { listObjectsArgs = ListObjectsArgs.builder() .bucket(bucketName) .prefix(prefix) .recursive(true) .build(); } Iterable<Result<Item>> chunks = client.listObjects(listObjectsArgs); Iterator<Result<Item>> iterator = chunks.iterator(); while(iterator.hasNext()) { Result<Item> item = iterator.next(); chunkPaths.add(URLUtil.decode(item.get().objectName())); } return chunkPaths; } /** * 通过文件名字判断文件是否存在如果存在返回false否则返回true * @param bucketName 桶名称 * @param fileName 文件名称 * @return true|false */ @SneakyThrows public Boolean fileExists(String bucketName, String fileName) { boolean exist = true; try { if(client.statObject(StatObjectArgs.builder().bucket(bucketName).object(fileName).build()) == null){ exist = false; } } catch (Exception e) { exist = false; } return exist; } /** * 获取全部bucket * <p> * https://docs.minio.io/cn/java-client-api-reference.html#listBuckets */ @SneakyThrows public List<Bucket> getAllBuckets() { return client.listBuckets(); } /** * @param bucketName bucket名称 */ @SneakyThrows public Optional<Bucket> getBucket(String bucketName) { return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst(); } /** * @param bucketName bucket名称 */ @SneakyThrows public Boolean bucketExists(String bucketName) { return client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } /** * @param bucketName bucket名称 */ @SneakyThrows public void removeBucket(String bucketName) { client.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } /** * 根据文件前置查询文件 * * @param bucketName bucket名称 * @param prefix 前缀 * @param recursive 是否递归查询 * @return MinioItem 列表 */ @SneakyThrows public List<MinioItem> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) { List<MinioItem> objectList = new ArrayList<>(); Iterable<Result<Item>> objectsIterator = client.listObjects(ListObjectsArgs.builder() .bucket(bucketName) .prefix(prefix) .recursive(recursive) .build()); for (Result<Item> itemResult : objectsIterator) { if(itemResult.get() != null) { objectList.add(new MinioItem(itemResult.get())); } } return objectList; } /** * 获取文件外链 * * @param bucketName bucket名称 * @param objectName 文件名称 * @param expires 过期时间 <=7 * @return url */ @SneakyThrows public String getObjectUrl(String bucketName, String objectName, Integer expires) { return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(bucketName) .object(objectName) .expiry(expires).build()); } /** * 创建上传文件对象的外链 * * @param bucketName 存储桶名称 * @param objectName 欲上传文件对象的名称 * @param expiry 过期时间(分钟) 最大为7天 超过7天则默认最大值 * @return uploadUrl */ @SneakyThrows public String createUploadUrl(String bucketName, String objectName, Integer expiry) { return client.getPresignedObjectUrl( GetPresignedObjectUrlArgs.builder() .method(Method.PUT) .bucket(bucketName) .object(objectName) .expiry(expiry) .build() ); } /** * 获取文件 * * @param bucketName bucket名称 * @param objectName 文件名称 * @return 二进制流 */ @SneakyThrows public InputStream getObject(String bucketName, String objectName) { return client.getObject(GetObjectArgs.builder() .bucket(bucketName) .object(objectName).build()); } /** * 从指定桶中获取对象的前缀输入流 * * @param bucketName 桶名 * @param objectName 对象名 * @return 读取对象前1024字节的输入流,如果发生异常则返回null */ public InputStream getPerfixInputStream(String bucketName, String objectName){ // 读取文件的前1024字节 // 你可以根据需要调整这个值 long size = 1024; try { return client.getObject(GetObjectArgs.builder() .bucket(bucketName) // 文件的起始位置 .offset(0L) // 需要读取的字节数 .length(size) .object(objectName).build()); } catch (Exception e) { log.error(e.getMessage(),e); } return null; } /** * 下载到指定位置 * * @param bucketName bucket名称 * @param objectName 对象名称 * @param objectName 文件名称 * @return 二进制流 */ @SneakyThrows public void downloadObject(String bucketName, String objectName, String fileName) { client.downloadObject(DownloadObjectArgs.builder() .bucket(bucketName) .object(objectName) //必须指定文件名 .filename(fileName) .build()); } /** * 复制文件 * * @param srcBucketName Source bucket name * @param srcObjectName Source object name * @param bucketName 目标 bucket名称 * @param objectName 目标 文件名称 * @return 二进制流 */ @SneakyThrows public void copyObject(String srcBucketName, String srcObjectName, String bucketName, String objectName) { client.copyObject(CopyObjectArgs.builder() .source(CopySource.builder() .bucket(srcBucketName) .object(srcObjectName) .build()) .bucket(bucketName) .object(objectName) .build()); } /** * 上传文件 * * @param bucketName bucket名称 * @param objectName 文件名称 * @param stream 文件流 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject */ public void putObject(String bucketName, String objectName, InputStream stream) throws Exception { putObject(bucketName, objectName, stream, (long) stream.available(), "application/octet-stream"); } /** * 上传文件 * * @param bucketName bucket名称 * @param objectName 文件名称 * @param stream 文件流 * @param size 大小 * @param contextType 类型 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject */ public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception { client.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName).stream(stream, size, -1) .contentType(contextType) .build()); } /** * 获取文件信息 * * @param bucketName bucket名称 * @param objectName 文件名称 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject */ /*public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception { return client.statObject( StatObjectArgs.builder().bucket(bucketName).object(objectName).build()); }*/ /** * 删除文件 * * @param bucketName bucket名称 * @param objectName 文件名称 */ @SneakyThrows public void removeObject(String bucketName, String objectName) { client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); } /** * 删除文件 * * @param bucketName bucket名称 * @param fileNames 文件名称列表 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject */ @SneakyThrows public void removeObjects(String bucketName, List<String> fileNames) { fileNames.forEach(objectName -> { try { client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); } catch (Exception e) { log.error(e.getMessage(),e); } }); } /** * 删除文件 * * @param bucketName bucket名称 * @param fileNamePre 标识符 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject */ @SneakyThrows public void removeObjects(String bucketName, String fileNamePre) { final List<String> listObjectNames = this.listObjectNames(bucketName, fileNamePre); this.removeObjects(bucketName,listObjectNames); } @Override public void afterPropertiesSet() throws Exception { Assert.hasText(endpoint, "Minio url 为空"); Assert.hasText(accessKey, "Minio accessKey为空"); Assert.hasText(secretKey, "Minio secretKey为空"); this.client = MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); }}
4.初始化桶类
@Slf4jpublic class MinioBucketInit implements Runnable{ /** 算法文件存放的minio桶 */ public String[] buckets; private MinioTemplate minioTemplate; public MinioBucketInit(MinioTemplate minioTemplate,String[] buckets) { this.minioTemplate = minioTemplate; this.buckets = buckets; } @Override public void run() { if(buckets==null) { return; } for (int i = 0; i <buckets.length ; i++) { //判断桶是否存在 Boolean bucketNameExit = minioTemplate.bucketExists(buckets[i]); if(!bucketNameExit){ minioTemplate.createBucket(buckets[i]); } } }}
5.使用
log.debug("初始化minio的桶"); //判断有没有桶threadPoolTaskExecutor.execute(new MinioBucketInit(minioTemplate,new String[]{bucketName}));
//获取源文件InputStream inputStream = minioTemplate.getObject(attachment.getBucketName(), attachment.getFilePath()); //判断文件是否存在 Boolean fileExists = minioTemplate.fileExists(attachment.getBucketName(), attachment.getFilePath());//上传文件到miniominioTemplate.putObject(MinioBucketInit.ALGORITH_MBUCKET, path, inputStream);
6.注意
1.上传时如果流是空的,不上传不成功的
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树NIONIO概述151370 人正在系统学习中 本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报。