初始化项目模块
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -24,3 +24,7 @@
|
|||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
replay_pid*
|
replay_pid*
|
||||||
|
|
||||||
|
/huawei-obs-springboot-starter.iml
|
||||||
|
/huawei-obs-springboot-starter.ipr
|
||||||
|
/huawei-obs-springboot-starter.iws
|
||||||
|
/target/
|
||||||
|
|||||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
74
pom.xml
Normal file
74
pom.xml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.njcn</groupId>
|
||||||
|
<artifactId>minioss-springboot-starter</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>nexus-releases</id>
|
||||||
|
<name>Nexus Release Repository</name>
|
||||||
|
<url>http://192.168.1.13:8001/nexus/content/repositories/releases/</url>
|
||||||
|
</repository>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>nexus-snapshots</id>
|
||||||
|
<name>Nexus Snapshot Repository</name>
|
||||||
|
<url>http://192.168.1.13:8001/nexus/content/repositories/snapshots/</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<progressbar.version>0.5.3</progressbar.version>
|
||||||
|
<okhttp.version>4.8.1</okhttp.version>
|
||||||
|
<minio.version>8.2.1</minio.version>
|
||||||
|
</properties>
|
||||||
|
<description>灿能minioss组件提取的starter模块</description>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.njcn</groupId>
|
||||||
|
<artifactId>common-core</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.tongfei</groupId>
|
||||||
|
<artifactId>progressbar</artifactId>
|
||||||
|
<version>${progressbar.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>${okhttp.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.minio</groupId>
|
||||||
|
<artifactId>minio</artifactId>
|
||||||
|
<version>${minio.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
<version>2.3.12.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
24
src/main/java/com/njcn/minioss/bo/MinIoUploadResDTO.java
Normal file
24
src/main/java/com/njcn/minioss/bo/MinIoUploadResDTO.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package com.njcn.minioss.bo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hongawen
|
||||||
|
* @version 1.0.0
|
||||||
|
* @date 2022年10月16日 18:40
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MinIoUploadResDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 475040120689218785L;
|
||||||
|
private String minFileName;
|
||||||
|
private String minFileUrl;
|
||||||
|
|
||||||
|
public MinIoUploadResDTO(String minFileName, String minFileUrl) {
|
||||||
|
this.minFileName = minFileName;
|
||||||
|
this.minFileUrl = minFileUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
43
src/main/java/com/njcn/minioss/config/MinIoProperties.java
Normal file
43
src/main/java/com/njcn/minioss/config/MinIoProperties.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package com.njcn.minioss.config;
|
||||||
|
|
||||||
|
import io.minio.MinioClient;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hongawen
|
||||||
|
* @version 1.0.0
|
||||||
|
* @date 2022年10月16日 18:37
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ConfigurationProperties(prefix = "min.io")
|
||||||
|
public class MinIoProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minio 服务端ip
|
||||||
|
*/
|
||||||
|
private String endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minio 访问通行key
|
||||||
|
*/
|
||||||
|
private String accessKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minio 访问秘钥key
|
||||||
|
*/
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minio 桶名称
|
||||||
|
*/
|
||||||
|
private String bucket;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MinioClient getMinioClient() {
|
||||||
|
return MinioClient.builder()
|
||||||
|
.endpoint(endpoint).credentials(accessKey, secretKey).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
606
src/main/java/com/njcn/minioss/util/MinIoUtils.java
Normal file
606
src/main/java/com/njcn/minioss/util/MinIoUtils.java
Normal file
@@ -0,0 +1,606 @@
|
|||||||
|
package com.njcn.minioss.util;
|
||||||
|
|
||||||
|
import com.njcn.minioss.bo.MinIoUploadResDTO;
|
||||||
|
import com.njcn.minioss.config.MinIoProperties;
|
||||||
|
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.SneakyThrows;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties({MinIoProperties.class})
|
||||||
|
public class MinIoUtils {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MinioClient instance;
|
||||||
|
|
||||||
|
private static final String SEPARATOR_DOT = ".";
|
||||||
|
|
||||||
|
private static final String SEPARATOR_ACROSS = "-";
|
||||||
|
|
||||||
|
private static final String SEPARATOR_STR = "";
|
||||||
|
|
||||||
|
// 存储桶名称
|
||||||
|
private static final String chunkBucKet = "minio_bucket";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不排序
|
||||||
|
*/
|
||||||
|
public final static boolean NOT_SORT = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*/
|
||||||
|
public final static boolean SORT = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认过期时间(分钟)
|
||||||
|
*/
|
||||||
|
private final static Integer DEFAULT_EXPIRY = 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除分片
|
||||||
|
*/
|
||||||
|
public final static boolean DELETE_CHUNK_OBJECT = true;
|
||||||
|
/**
|
||||||
|
* 不删除分片
|
||||||
|
*/
|
||||||
|
public final static boolean NOT_DELETE_CHUNK_OBJECT = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断桶是否存在
|
||||||
|
*
|
||||||
|
* @param bucketName 桶名
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean bucketExists(String bucketName) {
|
||||||
|
try {
|
||||||
|
return instance.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建存储桶
|
||||||
|
* 创建 bucket
|
||||||
|
*
|
||||||
|
* @param bucketName 桶名
|
||||||
|
*/
|
||||||
|
public void makeBucket(String bucketName) {
|
||||||
|
try {
|
||||||
|
boolean isExist = bucketExists(bucketName);
|
||||||
|
if (!isExist) {
|
||||||
|
instance.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return java.util.List<java.lang.String>
|
||||||
|
* @Description 获取文件存储服务的所有存储桶名称
|
||||||
|
*/
|
||||||
|
public List<String> listBucketNames() {
|
||||||
|
List<Bucket> bucketList = listBuckets();
|
||||||
|
List<String> bucketListName = new ArrayList<>();
|
||||||
|
for (Bucket bucket : bucketList) {
|
||||||
|
bucketListName.add(bucket.name());
|
||||||
|
}
|
||||||
|
return bucketListName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return java.util.List<io.minio.messages.Bucket>
|
||||||
|
* @Description 列出所有存储桶
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
private List<Bucket> listBuckets() {
|
||||||
|
return instance.listBuckets();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对象文件名称列表
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param prefix 对象名称前缀(文件夹 /xx/xx/xxx.jpg 中的 /xx/xx/)
|
||||||
|
* @return objectNames
|
||||||
|
*/
|
||||||
|
public List<String> listObjectNames(String bucketName, String prefix) {
|
||||||
|
return listObjectNames(bucketName, prefix, NOT_SORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对象文件名称列表
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param prefix 对象名称前缀(文件夹 /xx/xx/xxx.jpg 中的 /xx/xx/)
|
||||||
|
* @param sort 是否排序(升序)
|
||||||
|
* @return objectNames
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public List<String> listObjectNames(String bucketName, String prefix, Boolean sort) {
|
||||||
|
boolean flag = bucketExists(bucketName);
|
||||||
|
if (flag) {
|
||||||
|
ListObjectsArgs listObjectsArgs;
|
||||||
|
if (null == prefix) {
|
||||||
|
listObjectsArgs = ListObjectsArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.recursive(true)
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
listObjectsArgs = ListObjectsArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.prefix(prefix)
|
||||||
|
.recursive(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
Iterable<Result<Item>> chunks = instance.listObjects(listObjectsArgs);
|
||||||
|
List<String> chunkPaths = new ArrayList<>();
|
||||||
|
for (Result<Item> item : chunks) {
|
||||||
|
chunkPaths.add(item.get().objectName());
|
||||||
|
}
|
||||||
|
if (sort) {
|
||||||
|
chunkPaths.sort(new Str2IntComparator(false));
|
||||||
|
}
|
||||||
|
return chunkPaths;
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在桶下创建文件夹,文件夹层级结构根据参数决定
|
||||||
|
*
|
||||||
|
* @param bucket 桶名称
|
||||||
|
* @param WotDir 格式为 xxx/xxx/xxx/
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public String createDirectory(String bucket, String WotDir) {
|
||||||
|
if (!this.bucketExists(bucket)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
instance.putObject(PutObjectArgs.builder().bucket(bucket).object(WotDir).stream(
|
||||||
|
new ByteArrayInputStream(new byte[]{}), 0, -1)
|
||||||
|
.build());
|
||||||
|
return WotDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除一个文件
|
||||||
|
*
|
||||||
|
* @param bucketName 桶名称
|
||||||
|
* @param objectName /xx/xx/xxx.jpg
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public boolean removeObject(String bucketName, String objectName) {
|
||||||
|
|
||||||
|
if (!bucketExists(bucketName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
instance.removeObject(
|
||||||
|
RemoveObjectArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.object(objectName)
|
||||||
|
.build());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bucketName 桶名称
|
||||||
|
* @param objectNames /xx/xx/xxx.jpg
|
||||||
|
* @return java.util.List<java.lang.String>
|
||||||
|
* @Description 删除指定桶的多个文件对象, 返回删除错误的对象列表,全部删除成功,返回空列表
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public List<String> removeObjects(String bucketName, List<String> objectNames) {
|
||||||
|
if (!bucketExists(bucketName)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
List<DeleteObject> deleteObjects = new ArrayList<>(objectNames.size());
|
||||||
|
for (String objectName : objectNames) {
|
||||||
|
deleteObjects.add(new DeleteObject(objectName));
|
||||||
|
}
|
||||||
|
List<String> deleteErrorNames = new ArrayList<>();
|
||||||
|
Iterable<Result<DeleteError>> results = instance.removeObjects(
|
||||||
|
RemoveObjectsArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.objects(deleteObjects)
|
||||||
|
.build());
|
||||||
|
for (Result<DeleteError> result : results) {
|
||||||
|
DeleteError error = result.get();
|
||||||
|
deleteErrorNames.add(error.objectName());
|
||||||
|
}
|
||||||
|
return deleteErrorNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取访问对象的外链地址
|
||||||
|
* 获取文件的下载url
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param objectName 对象名称
|
||||||
|
* @param expiry 过期时间(分钟) 最大为7天 超过7天则默认最大值
|
||||||
|
* @return viewUrl
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public String getObjectUrl(String bucketName, String objectName, Integer expiry) {
|
||||||
|
expiry = expiryHandle(expiry);
|
||||||
|
return instance.getPresignedObjectUrl(
|
||||||
|
GetPresignedObjectUrlArgs.builder()
|
||||||
|
.method(Method.GET)
|
||||||
|
.bucket(bucketName)
|
||||||
|
.object(objectName)
|
||||||
|
.expiry(expiry)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建上传文件对象的外链
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param objectName 欲上传文件对象的名称
|
||||||
|
* @return uploadUrl
|
||||||
|
*/
|
||||||
|
public String createUploadUrl(String bucketName, String objectName) {
|
||||||
|
return createUploadUrl(bucketName, objectName, DEFAULT_EXPIRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建上传文件对象的外链
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param objectName 欲上传文件对象的名称
|
||||||
|
* @param expiry 过期时间(分钟) 最大为7天 超过7天则默认最大值
|
||||||
|
* @return uploadUrl
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public String createUploadUrl(String bucketName, String objectName, Integer expiry) {
|
||||||
|
expiry = expiryHandle(expiry);
|
||||||
|
return instance.getPresignedObjectUrl(
|
||||||
|
GetPresignedObjectUrlArgs.builder()
|
||||||
|
.method(Method.PUT)
|
||||||
|
.bucket(bucketName)
|
||||||
|
.object(objectName)
|
||||||
|
.expiry(expiry)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 批量下载
|
||||||
|
// *
|
||||||
|
// * @param directory
|
||||||
|
// * @return
|
||||||
|
// */
|
||||||
|
// @SneakyThrows
|
||||||
|
// public List<String> downLoadMore(String bucket, String directory) {
|
||||||
|
// Iterable<io.minio.Result<Item>> objs = instance.listObjects(ListObjectsArgs.builder().bucket(bucket).prefix(directory).useUrlEncodingType(false).build());
|
||||||
|
// List<String> list = new ArrayList<>();
|
||||||
|
// for (io.minio.Result<Item> result : objs) {
|
||||||
|
// String objectName = null;
|
||||||
|
// objectName = result.get().objectName();
|
||||||
|
// ObjectStat statObject = instance.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build());
|
||||||
|
// if (statObject != null && statObject.length() > 0) {
|
||||||
|
// String fileurl = instance.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucket).object(statObject.name()).method(Method.GET).build());
|
||||||
|
// list.add(fileurl);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return list;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param multipartFile 文件
|
||||||
|
* @param bucketName 桶名
|
||||||
|
* @param directory image/
|
||||||
|
* @return java.lang.String
|
||||||
|
* @Description 文件上传
|
||||||
|
*/
|
||||||
|
public MinIoUploadResDTO upload(MultipartFile multipartFile, String bucketName, String directory) throws Exception {
|
||||||
|
if (!this.bucketExists(bucketName)) {
|
||||||
|
this.makeBucket(bucketName);
|
||||||
|
}
|
||||||
|
InputStream inputStream = multipartFile.getInputStream();
|
||||||
|
directory = Optional.ofNullable(directory).orElse("");
|
||||||
|
String minFileName = directory + minFileName(multipartFile.getOriginalFilename());
|
||||||
|
//上传文件到指定目录
|
||||||
|
instance.putObject(PutObjectArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.object(minFileName)
|
||||||
|
.contentType(multipartFile.getContentType())
|
||||||
|
.stream(inputStream, inputStream.available(), -1)
|
||||||
|
.build());
|
||||||
|
inputStream.close();
|
||||||
|
// 返回生成文件名、访问路径
|
||||||
|
return new MinIoUploadResDTO(minFileName, getObjectUrl(bucketName, minFileName, DEFAULT_EXPIRY));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件流上传
|
||||||
|
* @param inputStream 文件流
|
||||||
|
* @param bucketName 桶名
|
||||||
|
* @param directory image/
|
||||||
|
* @return java.lang.String
|
||||||
|
*/
|
||||||
|
public MinIoUploadResDTO uploadStream(InputStream inputStream, String bucketName, String directory, String fileName) throws Exception {
|
||||||
|
if (!this.bucketExists(bucketName)) {
|
||||||
|
this.makeBucket(bucketName);
|
||||||
|
}
|
||||||
|
directory = Optional.ofNullable(directory).orElse("");
|
||||||
|
String minFileName = directory + minFileName(fileName);
|
||||||
|
//上传文件到指定目录
|
||||||
|
instance.putObject(PutObjectArgs.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.object(minFileName)
|
||||||
|
.stream(inputStream, inputStream.available(), -1)
|
||||||
|
.build());
|
||||||
|
inputStream.close();
|
||||||
|
// 返回生成文件名、访问路径
|
||||||
|
return new MinIoUploadResDTO(minFileName, getObjectUrl(bucketName, minFileName, DEFAULT_EXPIRY));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param response
|
||||||
|
* @return java.lang.String
|
||||||
|
* @Description 下载文件
|
||||||
|
*/
|
||||||
|
// public void download(HttpServletResponse response, String bucketName, String minFileName) throws Exception {
|
||||||
|
// InputStream fileInputStream = instance.getObject(GetObjectArgs.builder()
|
||||||
|
// .bucket(bucketName)
|
||||||
|
// .object(minFileName).build());
|
||||||
|
// response.setHeader("Content-Disposition", "attachment;filename=" + minFileName);
|
||||||
|
// response.setContentType("application/force-download");
|
||||||
|
// response.setCharacterEncoding("UTF-8");
|
||||||
|
// IOUtils.copy(fileInputStream, response.getOutputStream());
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量创建分片上传外链
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param objectMD5 欲上传分片文件主文件的MD5
|
||||||
|
* @param chunkCount 分片数量
|
||||||
|
* @return uploadChunkUrls
|
||||||
|
*/
|
||||||
|
public List<String> createUploadChunkUrlList(String bucketName, String objectMD5, Integer chunkCount) {
|
||||||
|
if (null == bucketName) {
|
||||||
|
bucketName = chunkBucKet;
|
||||||
|
}
|
||||||
|
if (null == objectMD5) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
objectMD5 += "/";
|
||||||
|
if (null == chunkCount || 0 == chunkCount) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<String> urlList = new ArrayList<>(chunkCount);
|
||||||
|
for (int i = 1; i <= chunkCount; i++) {
|
||||||
|
String objectName = objectMD5 + i + ".chunk";
|
||||||
|
urlList.add(createUploadUrl(bucketName, objectName, DEFAULT_EXPIRY));
|
||||||
|
}
|
||||||
|
return urlList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建指定序号的分片文件上传外链
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param objectMD5 欲上传分片文件主文件的MD5
|
||||||
|
* @param partNumber 分片序号
|
||||||
|
* @return uploadChunkUrl
|
||||||
|
*/
|
||||||
|
public String createUploadChunkUrl(String bucketName, String objectMD5, Integer partNumber) {
|
||||||
|
if (null == bucketName) {
|
||||||
|
bucketName = chunkBucKet;
|
||||||
|
}
|
||||||
|
if (null == objectMD5) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
objectMD5 += "/" + partNumber + ".chunk";
|
||||||
|
return createUploadUrl(bucketName, objectMD5, DEFAULT_EXPIRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分片文件名称列表
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param ObjectMd5 对象Md5
|
||||||
|
* @return objectChunkNames
|
||||||
|
*/
|
||||||
|
public List<String> listChunkObjectNames(String bucketName, String ObjectMd5) {
|
||||||
|
if (null == bucketName) {
|
||||||
|
bucketName = chunkBucKet;
|
||||||
|
}
|
||||||
|
if (null == ObjectMd5) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return listObjectNames(bucketName, ObjectMd5, SORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分片名称地址HashMap key=分片序号 value=分片文件地址
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param ObjectMd5 对象Md5
|
||||||
|
* @return objectChunkNameMap
|
||||||
|
*/
|
||||||
|
public Map<Integer, String> mapChunkObjectNames(String bucketName, String ObjectMd5) {
|
||||||
|
if (null == bucketName) {
|
||||||
|
bucketName = chunkBucKet;
|
||||||
|
}
|
||||||
|
if (null == ObjectMd5) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<String> chunkPaths = listObjectNames(bucketName, ObjectMd5);
|
||||||
|
if (null == chunkPaths || chunkPaths.size() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Map<Integer, String> chunkMap = new HashMap<>(chunkPaths.size());
|
||||||
|
for (String chunkName : chunkPaths) {
|
||||||
|
Integer partNumber = Integer.parseInt(chunkName.substring(chunkName.indexOf("/") + 1, chunkName.lastIndexOf(".")));
|
||||||
|
chunkMap.put(partNumber, chunkName);
|
||||||
|
}
|
||||||
|
return chunkMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并分片文件成对象文件
|
||||||
|
*
|
||||||
|
* @param chunkBucKetName 分片文件所在存储桶名称
|
||||||
|
* @param composeBucketName 合并后的对象文件存储的存储桶名称
|
||||||
|
* @param chunkNames 分片文件名称集合
|
||||||
|
* @param objectName 合并后的对象文件名称
|
||||||
|
* @return true/false
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public boolean composeObject(String chunkBucKetName, String composeBucketName, List<String> chunkNames, String objectName, boolean isDeleteChunkObject) {
|
||||||
|
if (null == chunkBucKetName) {
|
||||||
|
chunkBucKetName = chunkBucKet;
|
||||||
|
}
|
||||||
|
List<ComposeSource> sourceObjectList = new ArrayList<>(chunkNames.size());
|
||||||
|
for (String chunk : chunkNames) {
|
||||||
|
sourceObjectList.add(
|
||||||
|
ComposeSource.builder()
|
||||||
|
.bucket(chunkBucKetName)
|
||||||
|
.object(chunk)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
instance.composeObject(
|
||||||
|
ComposeObjectArgs.builder()
|
||||||
|
.bucket(composeBucketName)
|
||||||
|
.object(objectName)
|
||||||
|
.sources(sourceObjectList)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
if (isDeleteChunkObject) {
|
||||||
|
removeObjects(chunkBucKetName, chunkNames);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并分片文件成对象文件
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param chunkNames 分片文件名称集合
|
||||||
|
* @param objectName 合并后的对象文件名称
|
||||||
|
* @return true/false
|
||||||
|
*/
|
||||||
|
public boolean composeObject(String bucketName, List<String> chunkNames, String objectName) {
|
||||||
|
return composeObject(chunkBucKet, bucketName, chunkNames, objectName, NOT_DELETE_CHUNK_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并分片文件成对象文件
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param chunkNames 分片文件名称集合
|
||||||
|
* @param objectName 合并后的对象文件名称
|
||||||
|
* @return true/false
|
||||||
|
*/
|
||||||
|
public boolean composeObject(String bucketName, List<String> chunkNames, String objectName, boolean isDeleteChunkObject) {
|
||||||
|
return composeObject(chunkBucKet, bucketName, chunkNames, objectName, isDeleteChunkObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并分片文件,合并成功后删除分片文件
|
||||||
|
*
|
||||||
|
* @param bucketName 存储桶名称
|
||||||
|
* @param chunkNames 分片文件名称集合
|
||||||
|
* @param objectName 合并后的对象文件名称
|
||||||
|
* @return true/false
|
||||||
|
*/
|
||||||
|
public boolean composeObjectAndRemoveChunk(String bucketName, List<String> chunkNames, String objectName) {
|
||||||
|
return composeObject(chunkBucKet, bucketName, chunkNames, objectName, DELETE_CHUNK_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param originalFileName 原始名称
|
||||||
|
* @return java.lang.String
|
||||||
|
* @Description 生成上传文件名
|
||||||
|
*/
|
||||||
|
public String minFileName(String originalFileName) {
|
||||||
|
String suffix = originalFileName;
|
||||||
|
if (originalFileName.contains(SEPARATOR_DOT)) {
|
||||||
|
suffix = originalFileName.substring(originalFileName.lastIndexOf(SEPARATOR_DOT));
|
||||||
|
}
|
||||||
|
return UUID.randomUUID().toString().replace(SEPARATOR_ACROSS, SEPARATOR_STR).toUpperCase() + suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将分钟数转换为秒数
|
||||||
|
*
|
||||||
|
* @param expiry 过期时间(分钟数)
|
||||||
|
* @return expiry
|
||||||
|
*/
|
||||||
|
private static int expiryHandle(Integer expiry) {
|
||||||
|
expiry = expiry * 60;
|
||||||
|
if (expiry > 604800) {
|
||||||
|
return 604800;
|
||||||
|
}
|
||||||
|
return expiry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Str2IntComparator implements Comparator<String> {
|
||||||
|
private final boolean reverseOrder; // 是否倒序
|
||||||
|
|
||||||
|
public Str2IntComparator(boolean reverseOrder) {
|
||||||
|
this.reverseOrder = reverseOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(String arg0, String arg1) {
|
||||||
|
Integer intArg0 = Integer.parseInt(arg0.substring(arg0.indexOf("/") + 1, arg0.lastIndexOf(".")));
|
||||||
|
Integer intArg1 = Integer.parseInt(arg1.substring(arg1.indexOf("/") + 1, arg1.lastIndexOf(".")));
|
||||||
|
if (reverseOrder) {
|
||||||
|
return intArg1 - intArg0;
|
||||||
|
} else {
|
||||||
|
return intArg0 - intArg1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 根据url地址获取对象名称
|
||||||
|
* @author hongawen
|
||||||
|
* @date 2022/10/17 20:05
|
||||||
|
* @param objectUrl 对象地址
|
||||||
|
* @return String 对象名称
|
||||||
|
*/
|
||||||
|
public static String getObjectNameByUrl(String objectUrl) {
|
||||||
|
if (objectUrl.indexOf("?") < 0) {
|
||||||
|
return "unknownFile";
|
||||||
|
}
|
||||||
|
String objectName = objectUrl.substring(0, objectUrl.indexOf("?"));
|
||||||
|
return objectName.substring(objectName.lastIndexOf("/") + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/main/resources/META-INF/spring.factories
Normal file
5
src/main/resources/META-INF/spring.factories
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
|
com.njcn.minioss.config.MinIoProperties,\
|
||||||
|
com.njcn.minioss.util.MinIoUtils
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user