Sring Boot整合Minio实现图片上传功能
若依前后端分离版本整合Minio
一、docker下载Minio镜像
# 下载最新版Minio镜像 (等同于 : docker pull minio/minio:latest )
docker pull minio/minio
报错解决方案:Error response from daemon: Get “https://registry-1.docker.io/v2/“: context deadline exceeded-CSDN博客
结果:
二、创建目录
一个用来存放配置,一个用来存储上传文件的目录
启动前需要先创建Minio外部挂载的配置文件( /opt/minio/config),和存储上传文件的目录( /opt/minio/data)
mkdir -p /opt/minio/config
mkdir -p /opt/minio/data
三、创建Minio容器
docker run -d -p 9000:9000 --name minio \
-p 9001:9001 \
-e "MINIO_ACCESS_KEY=minio" \
-e "MINIO_SECRET_KEY=minio123" \
-v /opt/minio/data:/data \
-v /opt/minio/config:/root/.minio \
minio/minio server /data \
--console-address ":9001"
四、运行minio
访问地址:http://ip地址:9001/login
用户名:minio
密码:minio123
四、创建桶Buckets
1、找到创建桶的位置
2、输入桶名称:test
3、创建成功
4、bucket权限设置:将Access Policy改为public
5、用户创建
identity—>users—>Create User
用户名为minio密码为minio123,权限配置为读写,点击保存。
java配置信息中所配置的key就是此处的用户。
五、基本依赖和配置
1、在pom.xml文件中引入minio依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.1.0</version>
</dependency>
2、在yml文件里加上minio配置信息
#文件服务器
minio:
url: http://{这里填服务器的ip地址}:9000 服务器ip
access-key: minio 账号
secret-key: minio123 密码
bucket-name: test 桶名称,minio服务器配置
3、minio客户端配置类
package com.health.common.config;
import io.minio.MinioClient;
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;
/**
* Minio客户端注入
*/
@ConfigurationProperties(prefix = "minio")
@Configuration
public class MinioConfig {
@Value("${minio.accessKey}")
private static String accessKey;
@Value("${minio.secretKey}")
private static String secretKey;
@Value("${minio.url}")
private static String url;
/** 获取yml配置类里的桶名称*/
@Value("${minio.bucket-name}")
private static String bucketName;
public static String getUrl() {
return url;
}
public void setUrl(String url) {
MinioConfig.url = url;
}
public static String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
MinioConfig.accessKey = accessKey;
}
public static String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
MinioConfig.secretKey = secretKey;
}
public static String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
MinioConfig.bucketName = bucketName;
}
@Bean
public MinioClient getMinioClient() {
return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
}
}
4、 新增MinioUtil工具类
package com.health.common.utils.file;
import com.health.common.utils.ServletUtils;
import com.health.common.utils.spring.SpringUtils;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.http.Method;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
public class MinioUtil {
/**
* 上传文件
*
* @param bucketName 桶名称
* @param fileName
*
* @throws IOException
*/
public static String uploadFile(String bucketName,
String fileName,
MultipartFile multipartFile) throws IOException {
String url;
MinioClient minioClient = SpringUtils.getBean(MinioClient.class);
try (InputStream inputStream = multipartFile.getInputStream()) {
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.stream(inputStream, multipartFile.getSize(), -1)
.contentType(multipartFile.getContentType())
.build());
url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.bucket(bucketName)
.object(fileName)
.method(Method.GET)
.build());
url = url.substring(0, url.indexOf('?'));
return ServletUtils.urlDecode(url);
}
catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
}
5、FileUploadUtils工具类新增minio的相关配置,完整代码如下
package com.health.common.utils.file;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import com.health.common.config.MinioConfig;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.health.common.config.HealthConfig;
import com.health.common.constant.Constants;
import com.health.common.exception.file.FileNameLengthLimitExceededException;
import com.health.common.exception.file.FileSizeLimitExceededException;
import com.health.common.exception.file.InvalidExtensionException;
import com.health.common.utils.DateUtils;
import com.health.common.utils.StringUtils;
import com.health.common.utils.uuid.Seq;
/**
* 文件上传工具类
*
* @author ruoyi
*/
public class FileUploadUtils
{
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 默认上传的地址
*/
private static String defaultBaseDir = HealthConfig.getProfile();
/**
* Minio默认上传的地址
*/
private static final String bucketName = MinioConfig.getBucketName();
public static String getBucketName() {
return bucketName;
}
public static void setDefaultBaseDir(String defaultBaseDir)
{
FileUploadUtils.defaultBaseDir = defaultBaseDir;
}
public static String getDefaultBaseDir()
{
return defaultBaseDir;
}
/**
* 以默认配置进行文件上传
*
* @param file 上传的文件
* @return 文件名称
* @throws Exception
*/
public static final String upload(MultipartFile file) throws IOException
{
try
{
return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(baseDir, fileName);
}
/**
* 以默认BucketName配置上传到Minio服务器
*
* @param file 上传的文件
*
* @return 文件名称
*
* @throws Exception
*/
public static String uploadMinio(MultipartFile file) throws IOException {
try {
return uploadMinino(getBucketName(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 自定义bucketName配置上传到Minio服务器
*
* @param file 上传的文件
*
* @return 文件名称
*
* @throws Exception
*/
public static String uploadMinio(MultipartFile file,
String bucketName) throws IOException {
try {
return uploadMinino(bucketName, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
private static String uploadMinino(String bucketName,
MultipartFile file,
String[] allowedExtension) throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, InvalidExtensionException {
int fileNameLength = file.getOriginalFilename().length();
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
try {
String fileName = extractFilename(file);
return MinioUtil.uploadFile(bucketName, fileName, file);
}
catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
}
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc;
}
public static final String getPathFileName(String uploadDir, String fileName) throws IOException
{
int dirLastIndex = HealthConfig.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension))
{
extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
}
return extension;
}
}
6、CommonController.java自定义Minio服务器上传请求(com.health.web.controller.common)
/**
* 自定义 Minio 服务器上传请求
*/
@PostMapping("/uploadMinio")
public AjaxResult uploadFileMinio(MultipartFile file) {
try {
// 上传并返回新文件名称
String fileName = FileUploadUtils.uploadMinio(file);
AjaxResult ajax = AjaxResult.success();
ajax.put("url", fileName);
ajax.put("fileName", fileName);
ajax.put("newFileName", FileUtils.getName(fileName));
ajax.put("originalFilename", file.getOriginalFilename());
return ajax;
}
catch (Exception e) {
return AjaxResult.error(e.getMessage());
}
}
六、Vue3前端改写
分别修改:
src/components/ImageUpload/index.vue
src/components/FileUpload/index.vue
到此就全部结束了!!!
感谢🌹:若依框架(RuoYi)集成minio实现文件上传、预览 - 码匠的随手分享