Spring boot 集成Minio实现文件单文件上传
一:准备工作本机安装Minio客户端
1:官方下载minio客户端工具:https://dl.min.io/server/minio/release/windows-amd64/minio.exe
官网上提供了多种环境安装:https://docs.min.io/cn/,大家可以自己选择。
2:cmd进入命令行,到minio.exe存放目录:执行:minio.exe server D:/minio/Data(PS:Data是我用来存放文件的文件夹,这个随大家选择),执行完之后出现如图:
代表安装启动成功。浏览器访问:127.0.0.1:9000,出现如下:
使用上图的minioadmin登陆。
体验一下:
新建文件桶:
可以看到一个img桶已经被创建好了,接下来我们就可以手动上传文件了。
二:代码实现
- 我们在工程中POM文件中先引入minioCilent的sdk包。
<!-- 引入minio sdk客户端 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>6.0.8</version>
</dependency>
- 启动配置文件(application.yml)中添加如下:
spring :
## 设置传输文件最大容量,防止上传文件因为容量太大导致上传失败
servlet:
multipart:
maxFileSize: 2000MB
maxRequestSize: 2000MB
minio:
## 以下仅仅本机测试,项目中不同文件肯定肯定存放的位置不一样,所以bocket(桶名也是不固定的)
url: http://127.0.0.1:9000
accessKey: minioadmin
secretKey: minioadmin
bocket: file
- 创建MinioConfig配置POJO文件(读取配置文件关于minio配置参数)
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioClientConfig {
/**
* minio host
*/
private String url;
/**
* 接入账号
*/
private String accessKey;
/**
* 接入口令
*/
private String secretKey;
/**
* 文件存放桶名
*/
private String bocket;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getBocket() {
return bocket;
}
public void setBocket(String bocket) {
this.bocket = bocket;
}
}
- 创建工具类
生成文件服务器上唯一文件名
import java.time.LocalDate;
/**
* @Author: 张全成
* 该工具类目前只是生成文件在服务器上唯一文件名
* 后续会采用雪花算法生成唯一标识,
* 项目中建议大家自己或者借助平台生成的唯一ID
* @Date: 2020/5/17 12:22
* @Version 1.0
*/
public class FileNameUtils {
public static String getNextId (String prefix) {
String fileName = "";
// 生成6位数随机数
String random = String.valueOf((int) ((Math.random()*9+1)*100000));
fileName = new StringBuilder().append(prefix).append(LocalDate.now()).append(random).toString();
return fileName;
}
}
获取某天年,月,日工具类(生成目录使用)
import java.time.LocalDate;
/**
* 时间操作工具类
* @author 张全成
*/
public class TimeUtils {
/**
* 获取年月日:
* @param nowTime
* @param kind 00:年;01:月:02:日
* @return
*/
public static String getCode(LocalDate nowTime,String kind){
String code = "";
if ("00".equals(kind)) {
code = String.valueOf(nowTime.getYear());
} else if("01".equals(kind)) {
code = String.valueOf(nowTime.getMonthValue());
} else if ("02".equals(kind)) {
code = String.valueOf(nowTime.getDayOfMonth());
}
return code;
}
}
minioClient工具类
import com.zqc.fileprocess.config.MinioClientConfig;
import io.minio.MinioClient;
import io.minio.errors.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* @Author: 张全成
* @Date: 2020/5/17 13:28
* @Version 1.0
*/
public class MinioClientUtils {
private static MinioClient minioClient;
private static final Logger logger = LoggerFactory.getLogger(MinioClientUtils.class);
public static Boolean fileUpload(MultipartFile file, String filePath, String suffix, MinioClientConfig minioClientConfig) {
boolean flag = false;
// 先判断桶是否存在,如果不存在先创建桶
try {
if (!getMinioClient(minioClientConfig).bucketExists(suffix)) {
getMinioClient(minioClientConfig).makeBucket(suffix);
}
// 开始上传文件
InputStream inputStream = file.getInputStream();
getMinioClient(minioClientConfig).putObject(suffix,filePath,inputStream,inputStream.available(),file.getContentType());
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
public static MinioClient getMinioClient(MinioClientConfig clientConfig) {
if (minioClient == null) {
try {
minioClient = new MinioClient(clientConfig.getUrl(),clientConfig.getAccessKey(),clientConfig.getSecretKey());
} catch (Exception e) {
logger.info("creat minioClient fail");
e.printStackTrace();
}
}
return minioClient;
}
}
- 业务实现类
package com.zqc.fileprocess.service.impl;
import com.zqc.fileprocess.config.MinioClientConfig;
import com.zqc.fileprocess.service.FileProcessService;
import com.zqc.fileprocess.utils.FileNameUtils;
import com.zqc.fileprocess.utils.MinioClientUtils;
import com.zqc.fileprocess.utils.TimeUtils;
import org.aspectj.lang.annotation.Around;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDate;
/**
* @Author: 张全成
* @Date: 2020/5/17 13:24
* @Version 1.0
*/
@Service
public class FileProcessServiceImpl implements FileProcessService {
@Autowired
MinioClientConfig minioClientConfig;
@Override
public String fileUpload(MultipartFile file) {
// 文件名
String fileName = "";
// 文件格式
String prefix = "";
// 服务器上文件的相对路径
String filePath = "";
// 上传成功标识
boolean flag = false;
// 获取文件前缀
int index= file.getOriginalFilename().indexOf(".")+1;
prefix = file.getOriginalFilename().substring(index);
fileName = FileNameUtils.getNextId(prefix);
// 文件相对路径我这边设置成了/桶名/年/月/日/唯一文件名
LocalDate localDate = LocalDate.now();
filePath = new StringBuilder()
.append("/").append(TimeUtils.getCode(localDate,"00"))
.append("/").append(TimeUtils.getCode(localDate,"01"))
.append("/").append(TimeUtils.getCode(localDate,"02"))
.append("/").append(fileName).append(".").append(prefix).toString();
flag = MinioClientUtils.fileUpload(file,filePath,prefix,minioClientConfig);
if (flag){
return fileName;
} else {
return null;
}
}
}
- 测试入口Controller
package com.zqc.fileprocess.controller;
import com.zqc.fileprocess.service.FileProcessService;
import com.zqc.fileprocess.utils.FileNameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.lang.reflect.Field;
/**
* @Author: 张全成
* @Date: 2020/5/17 12:43
* @Version 1.0
*/
@RestController
@RequestMapping("/v1/fileProcess")
public class FileProcessController {
@Autowired
FileProcessService fileProcessService;
/**
* 单文件上传
* @param file
* @return 返回文件名,让业务方做记录
*/
@PostMapping("/upload")
public String fileUploa(@RequestParam MultipartFile file) {
String fileName = fileProcessService.fileUpload(file);
return fileName;
}
}
三:项目启动测试
- 启动项目
- postMan测试
发送之后可以得到返回参数是上传文件在文件服务器上文件名。
- 查看文件是否上传,两种方式确认:
1:在本机minio.exe文件所在目录中找到Data目录(就是安装启动时后面的目录,加粗部分:minio.exe server D:/minio/Data)
2:登陆127.0.0.1:9000,查看
以上就是spring boot 集成minio实现单文件上传demo,具体代码git地址:https://github.com/Thresh6300/fileProcess.git。后续会给大家提供单文件下载,批量上传,批量下载。至于没有文件删除这里解释一下:一般我们删除都是逻辑删除(就是数据库中将这条文件记录状态设置为删除状态),很少公司要求真正的删除文件服务器上的文件。