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。后续会给大家提供单文件下载,批量上传,批量下载。至于没有文件删除这里解释一下:一般我们删除都是逻辑删除(就是数据库中将这条文件记录状态设置为删除状态),很少公司要求真正的删除文件服务器上的文件。