springboot整合minio步骤
springboot整合minio十分的简单,接下来使用springboot整合一下minio。
一、导入依赖
首先需要导入minio的依赖。
<!--maven引入minio排除okhttp依赖并添加高版本的okhttp依赖-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.2</version>
<exclusions>
<exclusion>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.0</version>
</dependency>
不过这个okhttp还有一个坑,也是版本冲突,是在微服务中使用minio时的错误,详情可以看这篇文章:
二、添加配置类
第二步就是添加配置类,使用@Value可以方便之后修改相关参数
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient minioClient(){
return MinioClient.builder().endpoint(endpoint).credentials(accessKey,secretKey).build();
}
}
application.yml文件
minio:
minioUrlPrefix: http://10.102.115.112:9000/wlgzs/ # 文件访问前缀,加上文件在minio的路径就可以访问到文件
endpoint: http://10.102.115.112:9000 # minio服务地址,端口默认是9000
bucketName: wlgzs # minio存储桶的名称
accessKey: minioadmin # minio登录的账号即可
secretKey: minioadmin # minio登录的密码即可(哪个是账号密码记不太清了,错了互换一下试试)
三、minio工具类
minio有自己的api,为了方便使用,通常会封装成工具类,使用的时候直接调用即可
import cn.hutool.core.io.FastByteArrayOutputStream;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Component
@Slf4j
public class MinioUtil {
@Value("${minio.bucketName}")
private String bucketName;
@Resource
private MinioClient minioClient;
/**
* 查看存储bucket是否存在
* @return boolean
*/
public Boolean bucketExists(String bucketName) {
boolean found;
try {
found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
log.error("查看存储bucket是否存在时报错。报错类:" + MinioUtil.class);
return false;
}
return found;
}
/**
* 创建存储bucket
* @return Boolean
*/
public Boolean makeBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
log.error("创建存储bucket时报错。报错类:" + MinioUtil.class);
return false;
}
return true;
}
/**
* 删除存储bucket
* @return Boolean
*/
public Boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
log.error("删除存储bucket时报错。报错类:" + MinioUtil.class);
return false;
}
return true;
}
/**
* 获取全部bucket
*/
public List<Bucket> getAllBuckets() {
try {
return minioClient.listBuckets();
} catch (Exception e) {
log.error("获取全部存储bucket时报错。报错类:" + MinioUtil.class);
}
return null;
}
/**
* 文件上传 没有用md5值
* @param file 文件
* @return Boolean
*/
public String upload(MultipartFile file) {
String fileName = file.getOriginalFilename();
if (StringUtils.isEmpty(fileName)){
throw new RuntimeException();
}
try {
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName)
.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
//文件名称相同会覆盖
minioClient.putObject(objectArgs);
} catch (Exception e) {
log.error("上传文件时报错。报错类:" + MinioUtil.class);
return null;
}
return fileName;
}
/**
* 通过流上传
* @param inputStream 流
* @param fileName 文件名称,需要一个带后缀的文件名称如(a.jpg)
* @return
*/
public String uploadFileStream(InputStream inputStream, String fileName){
try {
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName)
.stream(inputStream, inputStream.available(), -1).build();
minioClient.putObject(objectArgs);
}catch (Exception e) {
log.error("上传文件流时报错。报错类:" + MinioUtil.class);
e.printStackTrace();
return null;
}
return fileName;
}
/**
* 预览图片
*/
public String preview(String fileName){
// 查看文件地址
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build();
try {
return minioClient.getPresignedObjectUrl(build);
} catch (Exception e) {
log.error("预览文件时报错。报错类:" + MinioUtil.class);
}
return null;
}
/**
* 文件下载
* @param fileName 文件名称
* @param res response
*/
public void download(String fileName, HttpServletResponse res) {
GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName)
.object(fileName).build();
try (GetObjectResponse response = minioClient.getObject(objectArgs)){
byte[] buf = new byte[1024];
int len;
try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){
while ((len=response.read(buf))!=-1){
os.write(buf,0,len);
}
os.flush();
byte[] bytes = os.toByteArray();
res.setCharacterEncoding("utf-8");
// 设置强制下载不打开
// res.setContentType("application/force-download");
res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
try (ServletOutputStream stream = res.getOutputStream()){
stream.write(bytes);
stream.flush();
}
}
} catch (Exception e) {
log.error("下载传文件时报错。报错类:" + MinioUtil.class);
}
}
/**
* 查看文件对象
* @return 存储bucket内文件对象信息
*/
public List<Item> listObjects() {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucketName).build());
List<Item> items = new ArrayList<>();
try {
for (Result<Item> result : results) {
items.add(result.get());
}
} catch (Exception e) {
log.error("查看文件对象时报错。报错类:" + MinioUtil.class);
return null;
}
return items;
}
/**
* 删除文件
*/
public boolean remove(String fileName){
try {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
}catch (Exception e){
log.error("删除文件时报错。报错类:" + MinioUtil.class);
return false;
}
return true;
}
/**
* 判断文件是否存在
*/
public Boolean checkFileIsExist(String objectName) {
try {
minioClient.statObject(
StatObjectArgs.builder().bucket(bucketName).object(objectName).build()
);
} catch (Exception e) {
return false;
}
return true;
}
}
四、测试
为了方便,我直接在controller中测试,不写service层了
@Controller
@ResponseBody
public class Minio_controller {
@Value("${minio.minioUrlPrefix}")
private String minioUrlPrefix;
@Autowired
private MinioUtil minioUtil;
//文件上传返回url
@PostMapping("/testUpload")
public String testUpload(@RequestParam("file") MultipartFile file) {
String objectName = minioUtil.upload(file);
if (null != objectName) {
return minioUrlPrefix + objectName;
}
return "error";
}
}
上传成功。