1.下载
地址:MinIO下载
wget 下载:
wget http://dl.minio.org.cn/server/minio/release/linux-amd64/minio
离线下载:https://dl.min.io/server/minio/release/linux-amd64/minio
2.安装
2.1新建目录
mkdir minio
2.2 给权限
chmod +x minio
2.3直接启动
./minio server data
(data是存储文件的目录,默认在当前目录下)
9000 是默认端口
3.配置
在启动后,就看到了警告,由于minio分配的是动态端口,所以需要绑定指定的端口
启动前需要修改账号密码
vim /etc/profile
在最后添加
export MINIO_ROOT_USER=minio
export MINIO_ROOT_PASSWORD=minio
立即生效
source /etc/profile
3.1映射端口
在启动的时候可以直接绑定
去到minio目录
后台启动
nohup ./minio server data --console-address :9999 &
绑定端口:--console-address :9999
存储信息的目录:data
查看日志
tail -200f nohup.out
再开放9999端口即可
访问地址:http://192.168.0.201:9999/login
用设置好的用户名和密码登录即可
二、集成到springboot中
1. 加入依赖
<!-- Minio 文件存储 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.1</version>
</dependency>
2. 添加配置
# Minio配置
minio:
url: http://localhost:9000
accessKey: minio
secretKey: minio
bucketName: test
3.配置类
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig
{
/**
* 服务地址
*/
private static String url;
/**
* 用户名
*/
private static String accessKey;
/**
* 密码
*/
private static String secretKey;
/**
* 存储桶名称
*/
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. 文件上传工具类
/**
* 文件上传工具类
*
*/
public class FileUploadUtils
{
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 以默认BucketName配置上传到Minio服务器
*
* @param file 上传的文件
* @return 文件名称
* @throws Exception
*/
public static final 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 final 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 final String uploadMinino(String bucketName, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils2.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils2.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
try
{
String fileName = extractFilename(file);
String pathFileName = MinioUtils.uploadFile(bucketName, fileName, file);
return pathFileName;
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件大小校验
*
* @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);
}
}
}
/**
* 编码文件名
*/
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;
}
/**
* 获取文件名的后缀
*
* @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;
}
/**
* 判断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;
}
}
5.minio工具类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class MinioUtils {
@Value("${minio.bucketName}")
public String bucketName;
@Autowired
private MinioClient minioClient;
/**
* 上传文件
*
* @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);
}
}
/**
* 判断桶是否存在,如果存在返回true,如果不存在返回false
*
* @param bucketName
* @return
*/
@SneakyThrows
public Boolean existBucket(String bucketName) {
boolean exist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!exist) {
return false;
}
return true;
}
/**
* 创建桶
*
* @param bucketName
* @return
*/
@SneakyThrows
public void makeBucket(String bucketName) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
/**
* 上传对象
*
* @param objectName
* @param file
* @return
* @throws Exception
*/
@SneakyThrows
public void putObject(String objectName, MultipartFile file) {
//判断 桶是否存在
boolean flag = existBucket(bucketName);
if (flag) {
PutObjectArgs args = PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.contentType(file.getContentType())
.stream(file.getInputStream(), file.getSize(), -1)
.build();
minioClient.putObject(args);
}
}
/**
* 删除对象
*
* @param objectName
* @return
* @throws Exception
*/
@SneakyThrows
public boolean removeObject(String objectName) {
boolean flag = existBucket(bucketName);
if (flag) {
RemoveObjectArgs args = RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build();
minioClient.removeObject(args);
return true;
}
return false;
}
/**
* 获取对象信息
*
* @param objectName
* @return
* @throws Exception
*/
@SneakyThrows
public StatObjectResponse getMessage(String objectName) {
boolean flag = existBucket(bucketName);
if (flag) {
StatObjectResponse statObject = minioClient.statObject(StatObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build());
return statObject;
}
return null;
}
/**
* 下载
*
* @param filename
* @param response
*/
public void getObject(String filename, HttpServletResponse response) {
InputStream in = null;
OutputStream out = null;
try {
in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(filename).build());
int length = 0;
byte[] buffer = new byte[1024];
out = response.getOutputStream();
response.reset();
response.addHeader("Content-Disposition",
" attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
response.setContentType("application/octet-stream");
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
controller
测试
@PostMapping("/uploadMinio")
public R uploadFileMinio(MultipartFile file) throws Exception
{
try
{
// 上传并返回新文件名称
String fileName = FileUploadUtils.uploadMinio(file);
return R.ok(fileName);
}
catch (Exception e)
{
return R.fail(e.getMessage());
}
}