一、minio环境部署
1.下载minio
官网下载地址:https://min.io/download
2.安装minio
1.下载之后,得到minio.exe文件
2.建立文件夹,用于存放minio的文件数据(我自己设的data文件夹)
3.运行minio
1.运行minio服务:E:\Minio\package minio.exe server E:\Minio\data
2.具体路径根据自设的文件夹路径定
二、整合springboot
1.配置maven环境
在pom.xml里写入minio的依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<properties>
<minio.version>8.3.5</minio.version>
</properties>
2.配置yml文件
在application.yml中添加下列配置
minio:
# 服务器访问地址
endpoint: http://10.40.16.214:9000
#用户名
accessKey: minioadmin
# 密码
secretKey: minioadmin
# 默认桶名
bucketName: hirain
3.注入minio客户端
注入minio客户端
import io.minio.MinioClient;
import lombok.Data;
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 {
private String endpoint;
private String accessKey;
private String secretKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
4.写minio工具类
写minio工具类
import com.hirain.common.entity.ResourceMessage;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Component
@Slf4j
public class MinioUtils {
@Value("${minio.bucketName}")
private String bucketName;
@Autowired
private MinioClient minioClient;
public String upload(String objectName, MultipartFile file) {
try (InputStream in = file.getInputStream()) {
PutObjectArgs objectArgs = PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(in, in.available(), -1)
.contentType(file.getContentType())
.build();
minioClient.putObject(objectArgs);
} catch (Exception e) {
e.printStackTrace();
}
return bucketName + File.separator + objectName;
}
public boolean download(String objectName, HttpServletResponse res, HttpServletRequest req) throws Exception {
GetObjectArgs objectArgs = GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.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.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
res.addHeader("Content-Disposition", "attachment;fileName=" + filenameEncoding(objectName, req));
try (ServletOutputStream stream = res.getOutputStream()) {
stream.write(bytes);
stream.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static String filenameEncoding(String filename, HttpServletRequest request) throws UnsupportedEncodingException {
String agent = request.getHeader("User-Agent");
if (agent.contains("MSIE")) {
filename = URLEncoder.encode(filename, "utf-8");
} else if (agent.contains("Firefox")) {
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes(StandardCharsets.UTF_8)) + "?=";
} else {
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
public boolean removeObject(String objectName) {
try {
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public boolean removeFolder(String objectName) {
try {
Iterable<Result<Item>> list = listObjects(objectName);
for (Result<Item> item : list) {
String itemName = item.get().objectName();
removeObject(itemName);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public Iterable<Result<DeleteError>> removeObjects(List<String> objects) {
return minioClient.removeObjects(RemoveObjectsArgs.builder()
.bucket(bucketName)
.objects(objects.stream()
.map(DeleteObject::new)
.collect(Collectors.toList()))
.build());
}
public List<ResourceMessage> listFolderObjects(String objectName) {
Iterable<Result<Item>> results = listObjects(objectName);
List<ResourceMessage> objectNameList = new ArrayList<>();
try {
for (Result<Item> result : results) {
String path = bucketName + '/' + result.get().objectName();
String url = getObjectUrl(result.get().objectName());
objectNameList.add(new ResourceMessage(path, url));
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return objectNameList;
}
public Iterable<Result<Item>> listObjects(String objectNames) {
return minioClient.listObjects(ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(objectNames)
.recursive(true)
.build());
}
public String getObjectUrl(String objectName){
GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
.bucket(bucketName)
.object(objectName)
.method(Method.GET).build();
String presignedObjectUrl = null;
try {
presignedObjectUrl = minioClient.getPresignedObjectUrl(args);
} catch (Exception e) {
e.printStackTrace();
}
return presignedObjectUrl;
}
public boolean isFolderExist(String objectName) {
boolean exist = false;
Iterable<Result<Item>> results = listObjects(objectName);
try {
for (Result<Item> result : results) {
Item item = result.get();
if (item.isDir() && objectName.equals(item.objectName())) {
exist = true;
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return exist;
}
public void existBucket(String name) {
try {
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder()
.bucket(name)
.build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(name)
.build());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean removeBucket() {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public List<Bucket> getAllBuckets() {
try {
return minioClient.listBuckets();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
三、测试效果
1.写controller接口
实现文件的上传,下载,删除,预览功能
import com.hirain.common.annotation.LogOperation;
import com.hirain.common.utils.Result;
import com.hirain.common.entity.ResourceMessage;
import com.hirain.common.minio.MinioUtils;
import com.hirain.constant.MinioPrefix;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Api(value = "文件云处理", tags = {"文件云处理"})
@RestController
@RequestMapping("/craftFile")
public class OssCraftController {
@Autowired
private MinioUtils minioUtil;
private final String category = MinioPrefix.CRAFT;
@PostMapping("/upload")
@ApiOperation("上传文件资源")
@LogOperation("上传文件资源")
public Result<String> uploadResources(@RequestParam("craftId") Long craftId, @RequestParam("stepId") Long stepId, @RequestParam("file") MultipartFile file) {
String originalFilename = file.getOriginalFilename();
if (StringUtils.isNotBlank(originalFilename)) {
String filename = originalFilename.substring(0, originalFilename.lastIndexOf("."));
String objectName = getFilePath(craftId, stepId, filename);
String upload = minioUtil.upload(objectName, file);
return new Result<String>().ok(upload);
} else {
return new Result<String>().error();
}
}
@DeleteMapping("delete/folder")
@ApiOperation("删除文件夹")
@LogOperation("删除文件夹")
public Result<Boolean> deleteResources(@RequestParam("craftId") Long craftId, @RequestParam("stepId") Long stepId) {
String folderPath = getFolderPath(craftId, stepId);
boolean result = minioUtil.removeFolder(folderPath);
return new Result<Boolean>().ok(result);
}
@DeleteMapping("delete/file")
@ApiOperation("删除单个文件")
@LogOperation("删除单个文件")
public Result<Boolean> deleteResources(@RequestParam("craftId") Long craftId, @RequestParam("stepId") Long stepId, @RequestParam("filename") String filename) {
String objectName = getFilePath(craftId, stepId, filename);
boolean result = minioUtil.removeObject(objectName);
return new Result<Boolean>().ok(result);
}
@GetMapping("download")
@ApiOperation("下载文件")
public Result<Boolean> download(@RequestParam("craftId") Long craftId, @RequestParam("stepId") Long stepId, @RequestParam("filename") String filename, HttpServletResponse res, HttpServletRequest req) throws Exception {
String objectName = getFilePath(craftId, stepId, filename);
boolean download = minioUtil.download(objectName, res, req);
return new Result<Boolean>().ok(download);
}
@GetMapping("/preview")
@ApiOperation("预览文件")
@LogOperation("预览文件")
public Result<String> getObjectUrl(@RequestParam("craftId") Long craftId, @RequestParam("stepId") Long stepId, @RequestParam("filename") String filename) {
String objectName = getFilePath(craftId, stepId, filename);
String url = minioUtil.getObjectUrl(objectName);
return new Result<String>().ok(url);
}
@PostMapping("/listObjects")
@ApiOperation("查询指定文件夹下,文件信息")
@LogOperation("查询指定文件夹下,文件信息")
public Result<Object> listObjects(@RequestParam("craftId") Long craftId, @RequestParam("stepId") Long stepId) {
String folderPath = getFolderPath(craftId, stepId);
List<ResourceMessage> objectNameList = minioUtil.listFolderObjects(folderPath);
return new Result<>().ok(objectNameList);
}
@PostMapping("/listAllObjects")
@ApiOperation("查询全部资源信息")
@LogOperation("查询全部资源信息")
public Result<Object> listAllObjects() {
String folderPath = "/";
List<ResourceMessage> objectNameList = minioUtil.listFolderObjects(folderPath);
return new Result<>().ok(objectNameList);
}
@PostMapping("/isFolderExist")
@ApiOperation("是否存在文件夹")
@LogOperation("是否存在文件夹")
public Result<Boolean> isFolderExist(@RequestParam("craftId") Long craftId, @RequestParam("stepId") Long stepId) {
String folderPath = getFolderPath(craftId, stepId);
boolean folderExist = minioUtil.isFolderExist(folderPath);
return new Result<Boolean>().ok(folderExist);
}
public String getFilePath(Long craftId, Long stepId, String fileName) {
return category + "/" + craftId + "/" + stepId + "/" + fileName;
}
public String getFolderPath(Long craftId, Long stepId) {
return category + "/" + craftId + "/" + stepId + "/";
}
}
2.查看minio云平台
1.登录网址 :http://127.0.0.1:9000
2.输入用户名minioadmin,密码minioadmin
3.可在此处对文件进行图形化界面管理