MinIO是一个开源的对象存储服务器,它兼容Amazon S3 API。它提供了一个简单而强大的存储解决方案,可以用于存储和检索任意大小的文件对象,如图片、视频、文档等。
1.安装与配置Minio
https://dl.min.io/server/minio/release/windows-amd64/https://dl.min.io/server/minio/release/windows-amd64/ cmd的方式打开minio.exe所在的文件夹
1.1 设置管理员账号和密码
set MINIO_ACCESS_KEY=minioadmin //创建账号
set MINIO_SECRET_KEY=minioadmin //创建密码
#这俩命令要与下面的运行命令一起同一命令框运行
#最新的minio用下面的命令更改默认用户密码
set MINIO_ROOT_USER=minioadmin
set MINIO_ROOT_PASSWORD=minioadmin
1.2 执行以下指令启动minio
minio.exe server P:\MinIo\minio --console-address ":9001" --address ":9000"
1.3 浏览器上访问9001端口
localhost:9090
登陆后可以创建buket
1.4 设置访问规则
进入管理页面之后,找到“Access Rules”选项并点击,添加访问规则,因为默认情况下桶里面的数据是不能访问的
点击“Add Access Rule”按钮添加访问规则
1.5 输入访问前缀、选择该前缀对应的访问权限
现在上传的文件就可以分享给别人了,但是分享连接有有效期
1.6 设置永久访问连接
1.6.1 下载mc客户端
https://dl.min.io/client/mc/release/windows-amd64/https://dl.min.io/client/mc/release/windows-amd64/ 将下载好的mc.exe放到与minio相同位置
1.6.2 设置永久访问连接
mc.exe config host add minio http://192.168.2.163:9000 minioadmin minioadmin --api S3v4
然后执行 mc anonymous set download minio/桶名,在将文件设置为公共读就可以通过 http://服务器ip:端口/桶名称/文件名称 直接访问到了
2. 在Spring Boot项目中使用minio
如果minio8导致版本冲突可以使用minio7.1.0
2.1 导入依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2.2 设置yml配置
spring:
# 配置文件上传大小限制
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB
minio:
endpoint: http://192.168.2.163:9000
accesskey: minioadmin
secretKey: minioadmin
bucketName: mall
2.3 创建minio配置类
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioConfiguration {
//
private String endpoint; //连接url
private String accesskey; //用户名
private String secretKey; //密码
@Bean
public MinioClient minioClient(){
return MinioClient.builder().endpoint(endpoint).credentials(accesskey,secretKey).build();
}
}
2.4 创建工具类
import io.minio.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.Data;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Data
@Component
public class MinioUtil {
@Resource
private MinioClient minioClient;
@Resource
private MinioConfiguration minioConfiguration;
// 桶名
@Value("${minio.bucketName}")
private String bucketName;
@Data
public class FileDetail {
private String name;
private long size;
}
/**
* description: 判断bucket是否存在,不存在则创建
*
* @return: void
*/
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();
}
}
/**
* 创建存储bucket
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean makeBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 删除存储bucket
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* description: 上传文件
*
* @param multipartFile
* @return: java.lang.String
*/
public List<String> upload(MultipartFile[] multipartFile) {
List<String> names = new ArrayList<>(multipartFile.length);
for (MultipartFile file : multipartFile) {
String fileName = file.getOriginalFilename();
String[] split = fileName.split("\\.");
if (split.length > 1) {
fileName = UUID.randomUUID().toString() + "." + split[1];
} else {
fileName = fileName + System.currentTimeMillis();
}
InputStream in = null;
try {
in = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.stream(in, in.available(), -1)
.contentType(file.getContentType())
.build()
);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 得到文件完整URL
fileName = minioConfiguration.getEndpoint() + "/" + bucketName + "/" + fileName;
names.add(fileName);
}
return names;
}
/**
* description: 下载文件
*
* @param fileName
* @return: org.springframework.http.ResponseEntity<byte [ ]>
*/
public ResponseEntity<byte[]> download(String fileName) {
ResponseEntity<byte[]> responseEntity = null;
InputStream in = null;
ByteArrayOutputStream out = null;
try {
in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
out = new ByteArrayOutputStream();
IOUtils.copy(in, out);
//封装返回值
byte[] bytes = out.toByteArray();
HttpHeaders headers = new HttpHeaders();
try {
headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
headers.setContentLength(bytes.length);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setAccessControlExposeHeaders(Arrays.asList("*"));
responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return responseEntity;
}
/**
* 查看文件对象
* @param bucketName 存储bucket名称
* @return 存储bucket内文件对象信息
*/
public List<FileDetail> listObjects(String bucketName) {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucketName).build());
List<FileDetail> objectItems = new ArrayList<>();
try {
for (Result<Item> result : results) {
Item item = result.get();
FileDetail fileDetail = new FileDetail();
fileDetail.setName(item.objectName());
fileDetail.setSize(item.size());
objectItems.add(fileDetail);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return objectItems;
}
/**
* 批量删除文件对象
* @param bucketName 存储bucket名称
* @param objects 对象名称集合
*/
public void removeObjects(String bucketName, List<String> objects) {
List<DeleteObject> dos =
objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
minioClient.removeObjects(
RemoveObjectsArgs.builder()
.bucket(bucketName)
.objects(dos).build());
}
}
2.5 上传文件
import com.woniuxy.minio.util.MinioUtil;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
@RestController
@RequestMapping("/file")
public class FileController {
@Resource
private MinioUtil minioUtil;
@PostMapping("/upload")
public Object upload(MultipartFile file){
return minioUtil.upload(new MultipartFile[]{file});
}
}