在当今的数字化时代,数据存储已经成为一项至关重要的任务。随着业务的增长和数据的增加,选择一个高效、可靠且易于管理的存储解决方案变得越来越重要。Minio是一个开源的云存储工具,具有强大的功能和可扩展性,为企业提供了可靠的存储解决方案。
一、Minio的特性
Minio是一个高性能、可扩展的对象存储服务器,具有以下特性:
二、Minio工具类示例代码
1、首先,您需要在项目的pom.xml文件中添加MinIO Java SDK的依赖项。
<dependency>
<groupId>io.miniogroupId>
<artifactId>minioartifactId>
<version>4.4.0version>
dependency>
2、接下来,您需要创建一个MinIO客户端配置对象,并指定MinIO服务器的URL、访问密钥和秘密密钥。您可以将这些值存储在环境变量或配置文件中。
minio.properties
minio.url=http://127.0.0.1:9000 #MinIO服务所在地址
minio.accessKey=admin #访问的key
minio.secretKey=admin123 #访问的秘钥
minio.bucketName=test #存储桶名称
3、读取配置类
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.minio.MinioClient;
@Configuration
public class MinioConfig {
/**
* 服务地址
*/
@Value("${minio.url}")
private String url;
/**
* 用户名
*/
@Value("${minio.accessKey}")
private String accessKey;
/**
* 密码
*/
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient getMinioClient() {
return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
}
}
以下是一个简单的Minio工具类示例代码,用于连接Minio服务器和操作存储桶和对象:
import io.minio.*;
import io.minio.http.Method;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class MinioClientUtil {
private static final Logger log = Logger.getLogger(MinioClientUtil.class);
@Autowired
private MinioClient minioClient;
/**
* 服务地址
*/
@Value("${minio.url}")
private String url;
/**
* 存储桶名称
*/
@Value("${minio.bucketName}")
private String bucketName;
public MinioClient getMinioClient() {
return minioClient;
}
// 操作存储桶
/**
* 创建存储桶
*
* @param bucketName
*/
public void makeBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
System.out.println("Error occurred while creating bucket: " + e);
}
}
// 删除存储桶
public boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
return true;
} catch (Exception e) {
System.out.println("Error occurred while removing bucket: " + e);
return false;
}
}
// 检查存储桶是否存在
public boolean bucketExists(String bucketName) {
try {
return minioClient.bucketExists(BucketExistsArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
System.out.println("Error occurred while checking bucket existence: " + e);
return false;
}
}
// 上传对象到存储桶中
public void putObject(String bucketName, String objectName, InputStream data, long dataSize) throws IOException {
try {
minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(data, dataSize, -1) // 设置输入流的数据大小和分段大小,-1表示不分段。
.build());
} catch (Exception e) {
System.out.println("Error occurred while uploading object: " + e);
} finally {
if (data != null) {
data.close(); // 关闭输入流。
}
}
}
//操作文件对象
/**
* 上传文件
* @param file
* @param filePath
* @return
*/
public boolean uploadFile(MultipartFile file, String filePath) {
boolean b = false;
try {
PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(filePath)
.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
minioClient.putObject(args);
b = true;
} catch (Exception e) {
b = false;
log.error("上传文件到minio失败!!" + e.getMessage());
}
return b;
}
public String uploadFileByUrl(MultipartFile file, String filePath) {
try {
PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(filePath)
.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
minioClient.putObject(args);
} catch (Exception e) {
throw new RuntimeException("上传文件到minio失败!!" + e.getMessage());
}
return url + "/" + bucketName + "/" + filePath;
}
/**
* 附件下载
*
* @param attachmentName 附件原始名称
* @param attachmentNameInServer 存储在文件服务器中的附件名称
* @param httpServletResponse httpServletResponse
*/
public void download(String attachmentName, String attachmentNameInServer,
HttpServletResponse httpServletResponse) {
try {
StatObjectResponse statObjectResponse = minioClient
.statObject(StatObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
httpServletResponse.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(attachmentName, "UTF-8"));
httpServletResponse.setContentType(statObjectResponse.contentType());
// httpServletResponse.setContentType("application/octet-stream");
httpServletResponse.setCharacterEncoding("UTF-8");
InputStream inputStream = minioClient
.getObject(GetObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
IOUtils.copy(inputStream, httpServletResponse.getOutputStream());
} catch (Exception e) {
throw new RuntimeException("minio下载文件失败!!" + e.getMessage());
}
}
/**
* 获取预览URL 注:.txt的附件会乱码,PDF正常 注:默认有效期7天
*
* @param bucketName 桶名称
* @param attachmentNameInServer 存储在文件服务器中的附件名称
* @return
*/
public String getPresignedUrl(String bucketName, String attachmentNameInServer) {
try {
minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET)
.bucket(bucketName).object(attachmentNameInServer).build());
} catch (Exception e) {
throw new RuntimeException("minio生成文件临时分享链接失败!!" + e.getMessage());
}
}
/**
* 删除附件
*
* @param bucketName 桶名称
* @param attachmentNameInServer 存储在文件服务器中的附件名称
*/
public void remove(String bucketName, String attachmentNameInServer) {
try {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
} catch (Exception e) {
throw new RuntimeException("minio删除文件失败!!" + e.getMessage());
}
}
public InputStream getFileInputStream(String attachmentNameInServer) {
InputStream inputStream = null;
try {
inputStream = minioClient
.getObject(GetObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
} catch (Exception e) {
throw new RuntimeException("minio下载文件失败!!" + e.getMessage());
}
return inputStream;
}
/**
* 多图片zip下载
*/
public void batchDownload(List<String> filenames, String zip, HttpServletResponse res, HttpServletRequest
req) {
try {
BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
boolean bucketExists = minioClient.bucketExists(bucketArgs);
BufferedOutputStream bos = null;
res.reset();
bos = new BufferedOutputStream(res.getOutputStream());
ZipOutputStream out = new ZipOutputStream(bos);
res.setHeader("Access-Control-Allow-Origin", "*");
for (int i = 0; i < filenames.size(); i++) {
GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName)
.object(filenames.get(i)).build();
InputStream object = minioClient.getObject(objectArgs);
byte buf[] = new byte[1024];
int length = 0;
res.setCharacterEncoding("utf-8");
res.setContentType("application/force-download");// 设置强制下载不打开
res.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
res.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoding(zip, req) + ".zip");
out.putNextEntry(new ZipEntry(filenames.get(i).substring(filenames.get(i).lastIndexOf("/") + 1)));
while ((length = object.read(buf)) > 0) {
out.write(buf, 0, length);
}
}
out.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String filenameEncoding(String filename, HttpServletRequest request) throws
UnsupportedEncodingException {
// 获得请求头中的User-Agent
String agent = request.getHeader("User-Agent");
// 根据不同的客户端进行不同的编码
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
三、总结
MinIO是一个高性能、可扩展、易用的开源对象存储服务。它兼容亚马逊S3云存储服务接口,可以方便地与现有的工具和生态系统集成。MinIO以其卓越的性能、可扩展性和易用性而闻名,适用于各种场景下的数据存储需求。无论是在单机环境下还是在分布式环境下,MinIO都可以提供可靠、高效的数据存储解决方案。