对象存储-MinIo
简介:
构建高性能的云原生数据、机器学习,大数据分析,海量存储的基础架构、MinIO支持各种应用程序数据工作负载。
特点:
- 高性能
- 可扩展性
- 云的原生支持
- 简单
- 开放全部源代码 + 企业级支持
- 与Amazon S3 兼容
一、搭建
支持Docker镜像部署
1、从 http:// hub.docker.com 拉取最新镜像
命令:docker pull minio/minio (此命令就等同于 : docker pull minio/minio:latest)
2、 创建目录
一个用来存放配置,一个用来存储上传文件的目录
启动前需要先创建Minio外部挂载的配置文件( /home/minio/config),和存储上传文件的目录( /home/minio/data)
mkdir -p /home/minio/config
mkdir -p /home/minio/data
3、创建Minio容器并运行
多行命令
docker run -p 9000:9000 -p 9090:9090 \
--net=host \
--name minio \
-d --restart=always \
-e "MINIO_ACCESS_KEY=minioadmin" \
-e "MINIO_SECRET_KEY=minioadmin" \
-v /home/minio/data:/data \
-v /home/minio/config:/root/.minio \
minio/minio server \
/data --console-address ":9090" -address ":9000"
单行命令
docker run -p 9000:9000 -p 9090:9090 --net=host --name minio -d --restart=always -e "MINIO_ACCESS_KEY=minioadmin" -e "MINIO_SECRET_KEY=minioadmin" -v /home/minio/data:/data -v /home/minio/config:/root/.minio minio/minio server /data --console-address ":9090" -address ":9000"
9090:客户端端口
9000:api端口(项目中所用)
MINIO_ACCESS_KEY :账号
MINIO_SECRET_KEY :密码(账号长度必须大于等于5,密码长度必须大于等于8位)
4、客户端访问
地址: http:// ip:9090
二、整合项目(SpringBoot项目)
1、application.yml
2、minio文件上传工具类
public class MinioUtil {
private static String minioUrl;
private static String minioName;
private static String minioPass;
private static String bucketName;
public static void setMinioUrl(String minioUrl) {
MinioUtil.minioUrl = minioUrl;
public static void setMinioName(String minioName) {
MinioUtil.minioName = minioName;
public static void setMinioPass(String minioPass) {
MinioUtil.minioPass = minioPass;
public static void setBucketName(String bucketName) {
MinioUtil.bucketName = bucketName;
public static String getMinioUrl() {
return minioUrl;
public static String getBucketName() {
return bucketName;
private static MinioClient minioClient = null;
* 上传文件
* @param file
* @return
public static String upload(MultipartFile file, String bizPath, String customBucket) {
String file_url = "";
//update-begin-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
bizPath=StrAttackFilter.filter(bizPath);
//update-end-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
String newBucket = bucketName;
if(oConvertUtils.isNotEmpty(customBucket)){
newBucket = customBucket;
try {
initMinio(minioUrl, minioName,minioPass);
// 检查存储桶是否已经存在
if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(newBucket).build())) {
log.info("Bucket already exists.");
} else {
// 创建一个名为ota的存储桶
minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build());
log.info("create a new bucket.");
InputStream stream = file.getInputStream();
// 获取文件名
String orgName = file.getOriginalFilename();
if("".equals(orgName)){
orgName=file.getName();
orgName = CommonUtils.getFileName(orgName);
String objectName = bizPath+"/"+orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
// 使用putObject上传一个本地文件到存储桶中。
if(objectName.startsWith("/")){
objectName = objectName.substring(1);
PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName)
.bucket(newBucket)
.contentType("application/octet-stream")
.stream(stream,stream.available(),-1).build();
minioClient.putObject(objectArgs);
stream.close();
file_url = minioUrl+newBucket+"/"+objectName;
}catch (Exception e){
log.error(e.getMessage(), e);
return file_url;
* 文件上传
* @param file
* @param bizPath
* @return
public static String upload(MultipartFile file, String bizPath) {
return upload(file,bizPath,null);
* 获取文件流
* @param bucketName
* @param objectName
* @return
public static InputStream getMinioFile(String bucketName,String objectName){
InputStream inputStream = null;
try {
initMinio(minioUrl, minioName, minioPass);
GetObjectArgs objectArgs = GetObjectArgs.builder().object(objectName)
.bucket(bucketName).build();
inputStream = minioClient.getObject(objectArgs);
} catch (Exception e) {
log.info("文件获取失败" + e.getMessage());
return inputStream;
* 删除文件
* @param bucketName
* @param objectName
* @throws Exception
public static void removeObject(String bucketName, String objectName) {
try {
initMinio(minioUrl, minioName,minioPass);
RemoveObjectArgs objectArgs = RemoveObjectArgs.builder().object(objectName)
.bucket(bucketName).build();
minioClient.removeObject(objectArgs);
}catch (Exception e){
log.info("文件删除失败" + e.getMessage());
* 获取文件外链
* @param bucketName
* @param objectName
* @param expires
* @return
public static String getObjectURL(String bucketName, String objectName, Integer expires) {
initMinio(minioUrl, minioName,minioPass);
GetPresignedObjectUrlArgs objectArgs = GetPresignedObjectUrlArgs.builder().object(objectName)
.bucket(bucketName)
.expiry(expires).build();
String url = minioClient.getPresignedObjectUrl(objectArgs);
return URLDecoder.decode(url,"UTF-8");
}catch (Exception e){
log.info("文件路径获取失败" + e.getMessage());
return null;
* 初始化客户端
* @param minioUrl
* @param minioName
* @param minioPass
* @return
private static MinioClient initMinio(String minioUrl, String minioName,String minioPass) {
if (minioClient == null) {
try {
minioClient = MinioClient.builder()
.endpoint(minioUrl)
.credentials(minioName, minioPass)
.build();
} catch (Exception e) {
e.printStackTrace();
return minioClient;
* 上传文件到minio
* @param stream
* @param relativePath
* @return
public static String upload(InputStream stream,String relativePath) throws Exception {
initMinio(minioUrl, minioName,minioPass);
if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
log.info("Bucket already exists.");
} else {
// 创建一个名为ota的存储桶
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
log.info("create a new bucket.");
PutObjectArgs objectArgs = PutObjectArgs.builder().object(relativePath)
.bucket(bucketName)
.contentType("application/octet-stream")
.stream(stream,stream.available(),-1).build();
minioClient.putObject(objectArgs);
stream.close();
return minioUrl+bucketName+"/"+relativePath;
}
3、controller
@PostMapping(value = "/uploadMinio")
public Result<?> uploadMinio(HttpServletRequest request) {
Result<?> result = new Result<>();
String bizPath = request.getParameter("biz");
if(oConvertUtils.isEmpty(bizPath)){
bizPath = "";
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("file");// 获取上传文件对象
String orgName = file.getOriginalFilename();// 获取文件名
orgName = CommonUtils.getFileName(orgName);
String file_url = MinioUtil.upload(file,bizPath);
if(oConvertUtils.isEmpty(file_url)){
return Result.error("上传失败,请检查配置信息是否正确!");
//保存文件信息
OSSFile minioFile = new OSSFile();
minioFile.setFileName(orgName);
minioFile.setUrl(file_url);
ossFileService.save(minioFile);
result.setMessage(file_url);
result.setSuccess(true);
return result;
}
4、前端组件
<a-upload
name="file"
:multiple="false"
:action="minioUploadAction"
:headers="tokenHeader"
:showUploadList="false"
:beforeUpload="beforeUpload"