本章内容:Springboot2.0引入MinIO实现文件的上传和下载功能,以及引入过程中遇到的Bug;
Docker 快速部署 MinIo
pom.xml中引入MinIO依赖
io.minio
minio
8.3.1
com.squareup.okhttp3
okhttp
com.squareup.okhttp3
okhttp
4.8.1
application.yml中配置MinIO
server:
port: 6001
min:
io:
secure: false
endpoint: http://127.0.0.1:9000
point: 80
accessKey: FASDFFSFDG7EXASDFAD
secretKey: eJalrSDtnFEMI/ASDF3GSD/bPxRfiCYEXASDFADEY
MinIO 属性配置文件以及将MinIO注入到spring管理
package net.sm.util.minio;
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;
/**
* @Author GGYYJJ
* @Date 2021/10/13 10:45
* @Version 1.0
* @Title
* @Desc
*/
@Configuration
@Data
public class MinIoConfig {
/**
* Minio 服务地址
*/
@Value("${min.io.endpoint}")
private String endpoint;
/**
* Minio 服务端口号
*/
@Value("${min.io.point}")
private Integer point;
/**
* Minio ACCESS_KEY
*/
@Value("${min.io.accessKey}")
private String accessKey;
/**
* Minio SECRET_KEY
*/
@Value("${min.io.secretKey}")
private String secretKey;
/**
* Minio 是否为https 请求,true 地址为http,false地址为http
*/
@Value("${min.io.secure}")
private boolean secure;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(endpoint, point, secure)
.credentials(accessKey, secretKey)
.build();
}
}
minio工具类,列出了常用文件操作,详细API需求请参考官方文档:
官网以及API | 中文API
package net.sm.util.minio;
import com.alibaba.fastjson.JSONObject;
import io.minio.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import jodd.io.FastByteArrayOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author GGYYJJ
* @Date 2021/10/12 13:28
* @Version 1.0
* @Title
* @Desc
*/
@Component
public class MinIoUtil {
@Autowired
private MinioClient minioClient;
/**
* 查看存储bucket是否存在
* @param bucketName 存储bucket
* @return boolean
*/
public Boolean bucketExists(String bucketName) {
Boolean found;
try {
found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return found;
}
/**
* 创建存储bucket
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean makeBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 删除存储bucket
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 文件上传
* @param file 文件
* @param bucketName 存储bucket
* @return Boolean
*/
public Boolean upload(MultipartFile file, String bucketName) {
try {
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(file.getOriginalFilename())
.stream(file.getInputStream(),file.getSize(),-1).contentType(file.getContentType()).build();
//文件名称相同会覆盖
minioClient.putObject(objectArgs);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 文件下载
* @param bucketName 存储bucket名称
* @param fileName 文件名称
* @param res response
* @return Boolean
*/
public void download(String bucketName, 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) {
e.printStackTrace();
}
}
/**
* 查看文件对象
* @param bucketName 存储bucket名称
* @return 存储bucket内文件对象信息
*/
public List listObjects(String bucketName) {
Iterable> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucketName).build());
List objectItems = new ArrayList<>();
try {
for (Result- result : results) {
Item item = result.get();
JSONObject objectItem = new JSONObject();
objectItem.put("object_name",item.objectName());
objectItem.put("size",item.size());
objectItems.add(objectItem);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return objectItems;
}
/**
* 批量删除文件对象
* @param bucketName 存储bucket名称
* @param objects 对象名称集合
*/
public Iterable
> removeObjects(String bucketName, List objects) {
List dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
Iterable> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
return results;
}
}
controller控制器入口方法,上传完之后可以在管理后台查看到。
package net.sm.controller;
import com.alibaba.fastjson.JSONObject;
import net.sm.util.minio.MinIoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
/**
* @Author GGYYJJ
* @Date 2021/9/29 17:48
* @Version 1.0
* @Title
* @Desc
*/
@RestController
@RequestMapping("/api/commodity/v1/")
public class CommodityController extends BaseController{
@Autowired
private MinIoUtil minIoUtil;
@RequestMapping("/uploadFile")
public void upload(@RequestParam("file") MultipartFile file) throws Exception {
System.out.println(minIoUtil.upload(file, "my-bucketname"));
}
/**
* minio下载文件
*/
@GetMapping("/download")
public void download(HttpServletResponse res){
minIoUtil.download("my-bucketname","logo.png", res);
}
}
PostMan测试图片上传
登录MinIO管理后台,找到对应的bucket下就可以看到上传成功的图片;
文件下载,打开浏览访问地址,http://127.0.0.1:6001/api/commodity/v1/download ,后台返回的文件流在浏览器进行下载;
1、在引入MinIo的时候,MinIO里面依赖的okhttp去除掉,并重新引入高版本的okhttp包。否则会报错;
okhttp3.RequestBody: file:/D:/Work20170505/mavn-repository/com/squareup/okhttp3/okhttp/3.14.9/okhttp-3.14.9.jar
Correct the classpath of your application so that it contains a single, compatible version of okhttp3.RequestBody
2、在Maven项目编译过程中,如果遇上缺少依赖,或是已引入依赖还报错的,在项目根目录执行mvn clean install;idea 要开启pom自动导入更新jar功能;