MinIO 安装
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
./minio server /data
启动成功:
[root@localhost minio]# ./minio server /data
Endpoint: http://***:9000 http://***:9000 http://127.0.0.1:9000
RootUser: minioadmin
RootPass: minioadmin
Browser Access:
http://***:9000 http://***:9000 http://127.0.0.1:9000
Command-line Access: https://docs.min.io/docs/minio-client-quickstart-guide
$ mc alias set myminio http://***:9000 minioadmin minioadmin
Object API (Amazon S3 compatible):
Go: https://docs.min.io/docs/golang-client-quickstart-guide
Java: https://docs.min.io/docs/java-client-quickstart-guide
Python: https://docs.min.io/docs/python-client-quickstart-guide
JavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide
.NET: https://docs.min.io/docs/dotnet-client-quickstart-guide
Detected default credentials 'minioadmin:minioadmin', please change the credentials immediately using 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD'
IAM initialization complete
问题1:浏览器无法访问“http://***:9000”
需要开放端口如:
1、开启防火墙
systemctl start firewalld
2、开放指定端口
firewall-cmd --zone=public --add-port=9000/tcp --permanent
命令含义:
--zone #作用域
--add-port=9000/tcp #添加端口,格式为:端口/通讯协议
--permanent #永久生效,没有此参数重启后失效
3、重启防火墙
firewall-cmd --reload
4、查看端口号
netstat -ntlp //查看当前所有tcp端口·
netstat -ntulp |grep 9000 //查看所有9000端口使用情况·
文档:http://docs.minio.org.cn/docs/
修改账户及密码
修改权限
chmod +x minio
执行命令:
export MINIO_ACCESS_KEY=accesskey(自行设置)
export MINIO_SECRET_KEY=secretkey(自行设置)
./minio server /data/bucket &
默认执行
[root@localhost ~]#cd /usr/local/minio
[root@localhost minio]# export MINIO_ACCESS_KEY=admin
[root@localhost minio]# export MINIO_SECRET_KEY=admin
[root@localhost minio]# nohup ./minio server /data
查看进程
ps -ef|grep minio
Spring Boot 集成 minio 及使用
添加依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.0</version>
</dependency>
添加配置
package com.zyy.common.utils.minio;
/**
* @author bfsz
* @version 1.0
* @description: Minio服务配置项
* @date 2021/4/19 11:45
*/
public class MinioConfig {
// "endPoint是一个URL,域名,IPv4或者IPv6地址"
public static String endpoint = "http://xxx.xx.xx.xx/";
// "TCP/IP端口号"
public static int port = 9000;
// "accessKey类似于用户ID,用于唯一标识你的账户"
public static String accessKey = "";
// "secretKey是你账户的密码"
public static String secretKey = "";
// "如果是true,则用的是https而不是http,默认值是true"
public static Boolean secure = false;
// "默认存储桶"
public static String bucketName = "wypt";
}
Minio工具类
package com.zyy.utils.minio;
import cn.hutool.core.util.RandomUtil;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.Result;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InvalidExpiresRangeException;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import net.coobird.thumbnailator.Thumbnails;
import net.minidev.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import static com.zyy.utils.thumbnailator.FileSuffixUtils.isPicture;
/**
* @author bfsz
* @version 1.0
* @description: Minio工具类
* @date 2021/4/19 11:49
*/
public class MinioUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(MinioUtil.class);
//失效时间 默认7天
private static final Integer DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;
private static MinioClient minioClient;
static {
try {
minioClient = new MinioClient(MinioConfig.endpoint, MinioConfig.port, MinioConfig.accessKey, MinioConfig.secretKey, MinioConfig.secure);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("初始化minio配置异常: 【{}】", e.fillInStackTrace());
}
}
/**
* @description: 检查存储桶是否存在
* @param: bucketName
* @return: boolean
* @author bfsz
* @date: 2021/4/19 11:56
*/
@SneakyThrows
public boolean bucketExists(String bucketName) {
boolean flag = false;
flag = minioClient.bucketExists(bucketName);
if (flag) {
return true;
}
return false;
}
/**
* @description: 创建存储桶
* @param: bucketName
* @return: boolean
* @author bfsz
* @date: 2021/4/19 11:57
*/
@SneakyThrows
public boolean makeBucket(String bucketName) {
boolean flag = bucketExists(bucketName);
if (!flag) {
minioClient.makeBucket(bucketName);
return true;
} else {
return false;
}
}
/**
* @description: 列出所有存储桶名称
* @param:
* @return: java.util.List<java.lang.String>
* @author bfsz
* @date: 2021/4/19 11:58
*/
@SneakyThrows
public List<String> listBucketNames() {
List<Bucket> bucketList = listBuckets();
List<String> bucketListName = new ArrayList<>();
for (Bucket bucket : bucketList) {
bucketListName.add(bucket.name());
}
return bucketListName;
}
/**
* @description: 列出所有存储桶
* @param:
* @return: java.util.List<io.minio.messages.Bucket>
* @author bfsz
* @date: 2021/4/19 11:58
*/
@SneakyThrows
public List<Bucket> listBuckets() {
return minioClient.listBuckets();
}
/**
* @description: 删除存储桶
* @param: bucketName
* @return: boolean
* @author bfsz
* @date: 2021/4/19 12:32
*/
@SneakyThrows
public boolean removeBucket(String bucketName) {
boolean flag = bucketExists(bucketName);
if (flag) {
Iterable<Result<Item>> myObjects = listObjects(bucketName);
for (Result<Item> result : myObjects) {
Item item = result.get();
// 有对象文件,则删除失败
if (item.size() > 0) {
return false;
}
}
// 删除存储桶,注意,只有存储桶为空时才能删除成功。
minioClient.removeBucket(bucketName);
flag = bucketExists(bucketName);
if (!flag) {
return true;
}
}
return false;
}
/**
* @description: 列出存储桶中的所有对象名称
* @param: bucketName
* @return: java.util.List<java.lang.String>
* @author bfsz
* @date: 2021/4/19 12:34
*/
@SneakyThrows
public List<String> listObjectNames(String bucketName) {
List<String> listObjectNames = new ArrayList<>();
boolean flag = bucketExists(bucketName);
if (flag) {
Iterable<Result<Item>> myObjects = listObjects(bucketName);
for (Result<Item> result : myObjects) {
Item item = result.get();
listObjectNames.add(item.objectName());
}
}
return listObjectNames;
}
/**
* @description: 列出存储桶中的所有对象
* @param: bucketName
* @return: java.lang.Iterable<io.minio.Result < io.minio.messages.Item>>
* @author bfsz
* @date: 2021/4/19 12:35
*/
@SneakyThrows
public Iterable<Result<Item>> listObjects(String bucketName) {
boolean flag = bucketExists(bucketName);
if (flag) {
return minioClient.listObjects(bucketName);
}
return null;
}
/**
* @description: 通过文件上传到对象
* @param: bucketName, objectName, fileName
* @return: boolean
* @author bfsz
* @date: 2021/4/19 12:35
*/
@SneakyThrows
public boolean putObject(String bucketName, String objectName, String fileName) {
boolean flag = bucketExists(bucketName);
if (flag) {
minioClient.putObject(bucketName, objectName, fileName, null);
ObjectStat statObject = statObject(bucketName, objectName);
if (statObject != null && statObject.length() > 0) {
return true;
}
}
return false;
}
/**
* @description: 文件上传
* @param: bucketName: 桶名
* ------- multipartFile:文件
* ------- userId: 用户id
* ------- tableName: 表名
* ------- tablePrimaryKeyId:表主键id
* ------- isCompression:是否压缩
* @return: void
* @author bfsz
* @date: 2021/4/19 15:44
*/
@SneakyThrows
public JSONObject uploadFile(String bucketName, MultipartFile multipartFile, String tableName, Integer tablePrimaryKeyId, Integer userId, Boolean isCompression) {
JSONObject res = new JSONObject();
res.put("code", 500);
// 判断上传文件是否为空
if (null == multipartFile || 0 == multipartFile.getSize()) {
res.put("msg", "上传文件不能为空");
return res;
}
// 判断存储桶是否存在,不存在则新建存储桶
if (!bucketExists(bucketName)) {
makeBucket(bucketName);
}
// 文件后缀名
String suffix = Objects.requireNonNull(multipartFile.getOriginalFilename()).substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
// 1、文件名
String filename = multipartFile.getOriginalFilename();
// 2、上传时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 3、用户ID
String UID = "UID" + userId + "_";
// 4、随机字符串
String fileString = RandomUtil.randomString(7);
// 文件存储的目录结构(文件名)
String pathFileName = tableName + "/" + tablePrimaryKeyId + "/" + sdf.format(new Date()) + "/" + UID + fileString + filename;
/**
* 判断是否是图片
* 判断是否超过了 500K
*/
if (isCompression && isPicture(suffix) && (1024 * 1024 * 0.5) <= multipartFile.getSize()) {
// 在项目根目录下的 upload 目录中生成临时文件
File newFile = new File(Thread.currentThread().getContextClassLoader().getResource("").getPath() + "upload" + UID + "." + suffix);
// 小于 1M 的
if ((1024 * 1024 * 0.1) <= multipartFile.getSize() && multipartFile.getSize() <= (1024 * 1024)) {
Thumbnails.of(multipartFile.getInputStream()).scale(1f).outputQuality(0.8f).toFile(newFile);
}
// 1 - 2M 的
else if ((1024 * 1024) < multipartFile.getSize() && multipartFile.getSize() <= (1024 * 1024 * 2)) {
Thumbnails.of(multipartFile.getInputStream()).scale(1f).outputQuality(0.6f).toFile(newFile);
}
// 2M 以上的
else if ((1024 * 1024 * 2) < multipartFile.getSize()) {
Thumbnails.of(multipartFile.getInputStream()).scale(1f).outputQuality(0.4f).toFile(newFile);
}
// 获取输入流
FileInputStream input = new FileInputStream(newFile);
// 转为 MultipartFile
MultipartFile multipartFile1 = new MockMultipartFile("file", newFile.getName(), "image/*", input);
// 开始上传
PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile1.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
putObjectOptions.setContentType(multipartFile1.getContentType());
minioClient.putObject(bucketName, pathFileName, multipartFile1.getInputStream(), putObjectOptions);
// 删除临时文件
newFile.delete();
// 返回状态以及图片路径
res.put("code", 200);
res.put("msg", "上传成功");
res.put("url", getObjectUrl(bucketName, pathFileName));
}
// 不需压缩,直接上传
else {
// 开始上传
PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
putObjectOptions.setContentType(multipartFile.getContentType());
minioClient.putObject(bucketName, pathFileName, multipartFile.getInputStream(), putObjectOptions);
// 返回状态以及图片路径
res.put("code", 200);
res.put("msg", "上传成功");
res.put("url", getObjectUrl(bucketName, pathFileName));
}
return res;
}
/**
* @description: 通过InputStream上传对象
* @param: bucketName, objectName, stream
* @return: boolean
* @author bfsz
* @date: 2021/4/19 12:39
*/
@SneakyThrows
public boolean putObject(String bucketName, String objectName, InputStream stream) {
boolean flag = bucketExists(bucketName);
if (flag) {
minioClient.putObject(bucketName, objectName, stream, new PutObjectOptions(stream.available(), -1));
ObjectStat statObject = statObject(bucketName, objectName);
if (statObject != null && statObject.length() > 0) {
return true;
}
}
return false;
}
/**
* @description: 上传文件返回地址
* @param: bucketName, objectName, stream
* @return: java.lang.String
* @author bfsz
* @date: 2021/4/19 12:40
*/
@SneakyThrows
public String putObjectUrl(String bucketName, String objectName, InputStream stream) {
boolean flag = putObject(bucketName, objectName, stream);
if (!flag) {
return "";
}
return getObjectUrl(bucketName, objectName);
}
/**
* @description: 以流的形式获取一个文件对象
* @param: bucketName, objectName
* @return: java.io.InputStream
* @author bfsz
* @date: 2021/4/19 12:41
*/
@SneakyThrows
public InputStream getObject(String bucketName, String objectName) {
boolean flag = bucketExists(bucketName);
if (flag) {
ObjectStat statObject = statObject(bucketName, objectName);
if (statObject != null && statObject.length() > 0) {
InputStream stream = minioClient.getObject(bucketName, objectName);
return stream;
}
}
return null;
}
/**
* @description: 以流的形式获取一个文件对象(断点下载)
* @param: bucketName
* objectName
* offset
* length
* @return: java.io.InputStream
* @author bfsz
* @date: 2021/4/19 12:42
*/
@SneakyThrows
public InputStream getObject(String bucketName, String objectName, long offset, Long length) {
boolean flag = bucketExists(bucketName);
if (flag) {
ObjectStat statObject = statObject(bucketName, objectName);
if (statObject != null && statObject.length() > 0) {
InputStream stream = minioClient.getObject(bucketName, objectName, offset, length);
return stream;
}
}
return null;
}
/**
* @description: 下载并将文件保存到本地
* @param: bucketName
* objectName
* fileName
* @return: boolean
* @author bfsz
* @date: 2021/4/19 12:43
*/
@SneakyThrows
public boolean getObject(String bucketName, String objectName, String fileName) {
boolean flag = bucketExists(bucketName);
if (flag) {
ObjectStat statObject = statObject(bucketName, objectName);
if (statObject != null && statObject.length() > 0) {
minioClient.getObject(bucketName, objectName, fileName);
return true;
}
}
return false;
}
/**
* @description: 删除一个对象
* @param: bucketName
* objectName
* @return: boolean
* @author bfsz
* @date: 2021/4/19 12:43
*/
@SneakyThrows
public JSONObject deleteFile(String bucketName, String objectName) {
JSONObject res = new JSONObject();
boolean flag = bucketExists(bucketName);
if (flag) {
minioClient.removeObject(bucketName, objectName);
res.put("code", "0");
res.put("msg", "success");
return res;
}
res.put("code", "1");
res.put("msg", "error");
return res;
}
/**
* @description: 删除指定桶的多个文件对象, 返回删除错误的对象列表,全部删除成功,返回空列表
* @param: bucketName
* objectNames
* @return: java.util.List<java.lang.String>
* @author bfsz
* @date: 2021/4/19 12:43
*/
@SneakyThrows
public List<String> removeObject(String bucketName, List<String> objectNames) {
List<String> deleteErrorNames = new ArrayList<>();
boolean flag = bucketExists(bucketName);
if (flag) {
Iterable<Result<DeleteError>> results = minioClient.removeObjects(bucketName, objectNames);
for (Result<DeleteError> result : results) {
DeleteError error = result.get();
deleteErrorNames.add(error.objectName());
}
}
return deleteErrorNames;
}
/**
* @description: 生成一个给HTTP GET请求用的presigned URL。
* 浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
* @param: bucketName
* objectName
* expires
* @return: java.lang.String
* @author bfsz
* @date: 2021/4/19 12:44
*/
@SneakyThrows
public String presignedGetObject(String bucketName, String objectName, Integer expires) {
boolean flag = bucketExists(bucketName);
String url = "";
if (flag) {
if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
throw new InvalidExpiresRangeException(expires,
"过期时间: 1 - " + DEFAULT_EXPIRY_TIME);
}
url = minioClient.presignedGetObject(bucketName, objectName, expires);
}
return url;
}
/**
* @description: 生成一个给HTTP PUT请求用的presigned URL。
* 浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
* @param: bucketName
* objectName
* expires
* @return: java.lang.String
* @author bfsz
* @date: 2021/4/19 12:47
*/
@SneakyThrows
public String presignedPutObject(String bucketName, String objectName, Integer expires) {
boolean flag = bucketExists(bucketName);
String url = "";
if (flag) {
if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
throw new InvalidExpiresRangeException(expires,
"expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
}
url = minioClient.presignedPutObject(bucketName, objectName, expires);
}
return url;
}
/**
* @description: 获取对象的元数据
* @param: bucketName
* objectName
* @return: io.minio.ObjectStat
* @author bfsz
* @date: 2021/4/19 12:47
*/
@SneakyThrows
public ObjectStat statObject(String bucketName, String objectName) {
boolean flag = bucketExists(bucketName);
if (flag) {
ObjectStat statObject = minioClient.statObject(bucketName, objectName);
return statObject;
}
return null;
}
/**
* @description: 文件访问路径
* @param: bucketName
* objectName
* @return: java.lang.String
* @author bfsz
* @date: 2021/4/19 12:47
*/
@SneakyThrows
public String getObjectUrl(String bucketName, String objectName) {
boolean flag = bucketExists(bucketName);
String url = "";
if (flag) {
url = minioClient.getObjectUrl(bucketName, objectName);
}
return url;
}
/**
* @description: 下载文件
* @param: bucketName
* fileName
* originalName
* response
* @return: void
* @author bfsz
* @date: 2021/4/19 12:47
*/
public void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response) {
try {
InputStream file = minioClient.getObject(bucketName, fileName);
String filename = new String(originalName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);
response.setHeader("Content-Disposition", "attachment;filename=" + filename);
ServletOutputStream servletOutputStream = response.getOutputStream();
int len;
byte[] buffer = new byte[1024];
while ((len = file.read(buffer)) > 0) {
servletOutputStream.write(buffer, 0, len);
}
servletOutputStream.flush();
file.close();
servletOutputStream.close();
} catch (ErrorResponseException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Controller测试
package com.zyy.controller;
import com.zyy.common.utils.minio.MinioUtil;
import com.zyy.repository.mapper.TbSysUserMapper;
import com.zyy.repository.entity.TbSysUser;
import net.minidev.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@Api(tags = "测试连接相关")
@RestController
@RequestMapping("/admin")
public class TestConnectController {
@Autowired
private TbSysUserMapper tbSysUserMapper;
private static final Logger LOGGER = LoggerFactory.getLogger(TestConnectController.class);
/**
* @description:文件上传测试
* @param: file
* projectId
* user_id
* @return: net.minidev.json.JSONObject
* @author bfsz
* @date: 2021/4/20 10:42
*/
@ApiOperation("文件上传测试接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件", defaultValue = "", required = true),
@ApiImplicitParam(name = "projectId", value = "任务ID", defaultValue = "", required = true),
@ApiImplicitParam(name = "user_id", value = "用户ID", defaultValue = "", required = true)
})
@RequestMapping(value = "/upload2", method = RequestMethod.POST)
public JSONObject uploadDemo(MultipartFile file, Integer projectId, Integer user_id) {
MinioUtil minioUtil = new MinioUtil();
return minioUtil.putObject("wypt", file, projectId, user_id, true);
}
@ApiOperation("文件删除测试接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "bucketName", value = "存储桶名称", defaultValue = "", required = true),
@ApiImplicitParam(name = "objectName", value = "文件名称", defaultValue = "", required = true)
})
@RequestMapping(value = "/delete2", method = RequestMethod.POST)
public JSONObject deleteDemo(String bucketName, String objectName) {
MinioUtil minioUtil = new MinioUtil();
return minioUtil.removeObject(bucketName, objectName);
}
}
thumbnailator 图片压缩上传至MinIO服务器
- Thumbnailator 是一个用来生成图像缩略图的 Java 类库,通过很简单的代码即可生成图片缩略图,也可直接对一整个目录的图片生成缩略图
- 支持图片缩放,区域裁剪,水印,旋转,保持比例
- https://blog.csdn.net/s12s12c12/article/details/106127596
- https://lizhou.blog.csdn.net/article/details/108321442
引入 maven 依赖
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.14</version>
</dependency>
增加文件类型判断工具类
package com.zyy.common.utils.thumbnailator;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* @author bfsz
* @version 1.0
* @description: 文件类型判断
* @date 2021/4/19 16:21
*/
public class FileSuffixUtils {
/**
* @param file
* @description: 判断文件是否为图片
* @param: imgName
* @return: boolean
* @author bfsz
* @date: 2021/4/19 16:22
*/
public static boolean isPicture(MultipartFile file) throws IOException {
BufferedImage bi = ImageIO.read(file.getInputStream());
if (bi == null) {
return false;
}
return true;
}
/**
* @description: 判断文件是否为图片
* @param: imgName
* @return: boolean
* @author bfsz
* @date: 2021/4/20 8:36
*/
public static boolean isPicture(String imgName) {
boolean flag = false;
if (StringUtils.isBlank(imgName)) {
return false;
}
String[] arr = {"bmp", "dib", "gif", "jfif", "jpe", "jpeg", "jpg", "png", "tif", "tiff", "ico"};
for (String item : arr) {
if (item.equals(imgName)) {
flag = true;
break;
}
}
return flag;
}
}
压缩上传
/**
* @description: 文件上传
* @param: bucketName: 桶名
* ------- multipartFile:文件
* ------- userId: 用户id
* ------- projectId:任务id
* ------- isCompression:是否压缩
* @return: void
* @author bfsz
* @date: 2021/4/19 15:44
*/
@SneakyThrows
public JSONObject putObject(String bucketName, MultipartFile multipartFile, Integer projectId, Integer userId, Boolean isCompression) {
JSONObject res = new JSONObject();
res.put("code", 500);
// 判断上传文件是否为空
if (null == multipartFile || 0 == multipartFile.getSize()) {
res.put("msg", "上传文件不能为空");
return res;
}
// 判断存储桶是否存在,不存在则新建存储桶
if (!bucketExists(bucketName)) {
makeBucket(bucketName);
}
// 文件后缀名
String suffix = Objects.requireNonNull(multipartFile.getOriginalFilename()).substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
// 文件名
String filename = multipartFile.getOriginalFilename();
// 上传时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 用户ID
String UID = "UID_" + userId + "_";
// 文件存储的目录结构(文件名)
String pathFileName = projectId + "/" + sdf.format(new Date()) + "/" + UID + filename;
/**
* 判断是否是图片
* 判断是否超过了 500K
*/
if (isCompression && isPicture(suffix) && (1024 * 1024 * 0.5) <= multipartFile.getSize()) {
// 在项目根目录下的 upload 目录中生成临时文件
File newFile = new File(Thread.currentThread().getContextClassLoader().getResource("").getPath() + "upload" + UID + "." + suffix);
// 小于 1M 的
if ((1024 * 1024 * 0.1) <= multipartFile.getSize() && multipartFile.getSize() <= (1024 * 1024)) {
Thumbnails.of(multipartFile.getInputStream()).scale(1f).outputQuality(0.8f).toFile(newFile);
}
// 1 - 2M 的
else if ((1024 * 1024) < multipartFile.getSize() && multipartFile.getSize() <= (1024 * 1024 * 2)) {
Thumbnails.of(multipartFile.getInputStream()).scale(1f).outputQuality(0.6f).toFile(newFile);
}
// 2M 以上的
else if ((1024 * 1024 * 2) < multipartFile.getSize()) {
Thumbnails.of(multipartFile.getInputStream()).scale(1f).outputQuality(0.4f).toFile(newFile);
}
// 获取输入流
FileInputStream input = new FileInputStream(newFile);
// 转为 MultipartFile
MultipartFile multipartFile1 = new MockMultipartFile("file", newFile.getName(), "image/*", input);
// 开始上传
PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile1.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
putObjectOptions.setContentType(multipartFile1.getContentType());
minioClient.putObject(bucketName, pathFileName, multipartFile1.getInputStream(), putObjectOptions);
// 删除临时文件
newFile.delete();
// 返回状态以及图片路径
res.put("code", 200);
res.put("msg", "上传成功");
res.put("url", getObjectUrl(bucketName, pathFileName));
}
// 不需压缩,直接上传
else {
// 开始上传
PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
putObjectOptions.setContentType(multipartFile.getContentType());
minioClient.putObject(bucketName, pathFileName, multipartFile.getInputStream(), putObjectOptions);
// 返回状态以及图片路径
res.put("code", 200);
res.put("msg", "上传成功");
res.put("url", getObjectUrl(bucketName, pathFileName));
}
return res;
}