这里我默认已经有服务器,并且安装了Minio的文件服务器。后续我在写一个安装Minio的文章。
这里我用的是Ruoyi的前后端Vue项目,有些方法不在的可以在Ruoyi的项目中找。Ruoyi
先引入Minio的Pom路径
<!--minio 文件服务器 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.0</version>
<exclusions>
<exclusion>
<artifactId>okhttp</artifactId>
<groupId>com.squareup.okhttp3</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.0</version>
</dependency>
因为我安装的是最新的版本,所以用的是比较高的8.4.0的版本
编写Minio的工具类
import com.google.common.collect.Maps;
import com.project.cost.common.utils.file.FileUploadUtils;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
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.Map;
/**
* @author rosszhang
*/
@Component
public class MinioUtil {
private static final Logger log = LoggerFactory.getLogger(MinioUtil.class);
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Value("${minio.bucketName}")
private String bucketName;
public String getBucketName() {
return bucketName;
}
private static MinioClient minioClient;
/**
* 初始化客户端
*
* @param endpoint
* @param accessKey
* @param secretKey
* @return
*/
private static MinioClient initMinio(String endpoint, String accessKey, String secretKey) {
if (minioClient == null) {
try {
minioClient = MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
/*// 检查存储通是否存在
Boolean exists = bucketExists(new MinioUtil().getBucketName());
// 如果不存在则,创建
if (!exists) {
makeBucket(new MinioUtil().getBucketName());
}*/
} catch (Exception e) {
log.error("初始化Minio客户端失败:{}", e.getMessage());
}
}
return minioClient;
}
/**
* 查看存储bucket是否存在
*
* @return boolean
*/
public static Boolean bucketExists(String bucketName) {
Boolean found;
try {
found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
log.error("查看存储bucket是否存在:{}", e.getMessage());
return false;
}
return found;
}
/**
* 创建存储bucket
*
* @return Boolean
*/
public static Boolean makeBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
log.error("创建MinIo存储bucket:{}", e.getMessage());
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("删除MinIo存储bucket:{}", e.getMessage());
return false;
}
return true;
}
/**
* 获取全部bucket
*/
public List<Bucket> getAllBuckets() {
try {
List<Bucket> buckets = minioClient.listBuckets();
return buckets;
} catch (Exception e) {
log.error("获取MinIo全部bucket:{}", e.getMessage());
}
return null;
}
/**
* 文件上传
*
* @param file 文件
* @return Boolean
*/
public Map<String, String> upload(MultipartFile file) {
initMinio(endpoint, accessKey, secretKey);
Map<String, String> result = Maps.newHashMap();
String originalFilename = file.getOriginalFilename();
if (StringUtils.isBlank(originalFilename)) {
throw new RuntimeException();
}
String filename = FileUploadUtils.extractFilename(file);
// String fileName = IdUtil.fastUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
// String objectName = DateUtil.localDateTimeFormatYear(LocalDateTime.now()) + "/" + fileName;
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("文件上传失败:{}", e.getMessage());
return null;
}
result.put("name", originalFilename);
result.put("newName", filename);
result.put("url", endpoint + "/" + bucketName + "/" + filename);
// UploadEntity uploadEntity=new UploadEntity();
// uploadEntity.setName(originalFilename );
// uploadEntity.setUrl(endpoint + "/" + bucketName + "/" + filename);
return result;
}
/**
* 将分钟数转换为秒数
*
* @param expiry 过期时间(分钟数)
* @return expiry
*/
private static int expiryHandle(Integer expiry) {
expiry = expiry * 60;
if (expiry > 604800) {
return 604800;
}
return expiry;
}
/**
* 获取访问对象的外链地址
* 获取文件的下载url
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @param expiry 过期时间(分钟) 最大为7天 超过7天则默认最大值
* @return viewUrl
*/
public String getObjectUrl(String bucketName, String objectName, Integer expiry) {
expiry = expiryHandle(expiry);
String presignedObjectUrl = null;
try {
presignedObjectUrl = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(objectName)
.expiry(expiry)
.build()
);
} catch (Exception e) {
log.error("Minio访问地址获取失败:{}", e.getMessage());
}
return presignedObjectUrl;
}
/**
* 预览图片
*
* @param fileName
* @return
*/
public String preview(String fileName) {
initMinio(endpoint, accessKey, secretKey);
// 查看文件地址
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build();
try {
String url = minioClient.getPresignedObjectUrl(build);
return url;
} catch (Exception e) {
log.error("预览Minio图片附件:{}", e.getMessage());
}
return null;
}
/**
* 文件下载
*
* @param fileName 文件名称
* @param res response
* @return Boolean
*/
public void download(String fileName, HttpServletResponse res) {
initMinio(endpoint, accessKey, secretKey);
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("Minio文件下载:{}", e.getMessage());
}
}
/**
* 查看文件对象
*
* @return 存储bucket内文件对象信息
*/
public List<Item> listObjects() {
initMinio(endpoint, accessKey, secretKey);
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("Minio查看文件对象:{}", e.getMessage());
return null;
}
return items;
}
/**
* 删除
*
* @param fileName
* @return
* @throws Exception
*/
public boolean remove(String fileName) {
initMinio(endpoint, accessKey, secretKey);
try {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
} catch (Exception e) {
log.error("删除Minio文件对象:{}", e.getMessage());
return false;
}
return true;
}
}
在项目文件的yml或者properties配置文件中配置Minio
# minio 文件服务器
minio:
endpoint: http://服务器IP地址:9001 #Minio服务所在地址
bucketName: cost #存储桶名称
# 此处的密码也可以使用私钥,具体怎么用,等我学习一下。或者自行百度
accessKey: minio的用户名 #访问的key
secretKey: minio的密码 #访问的秘钥
图片上传Controller
@RestController
@RequestMapping("/common")
public class CommonController {
@Autowired
private MinioUtil minioUtil;
/**
* 通用上传请求(单个)
*/
@PostMapping("/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception {
AjaxResult ajax = AjaxResult.success();
Map<String, String> upload = minioUtil.upload(file);
ajax.put("url", upload.get("url"));
ajax.put("fileName", upload.get("name"));
ajax.put("newFileName", FileUtils.getName(upload.get("name")));
ajax.put("originalFilename", file.getOriginalFilename());
return ajax;
}
}
这里使用Postman测试
测试成功之后可以在Minio的图形化界面查看是否成功
下面这个是我的个人公共号 只会写Bug的程序猿,大家可以关注一下。相互交流学习。
Ross zhang的博客
RossZhang的CSDN地址