Minio基于docker的基本使用
一、Minio的基本介绍
MinIO 是一种对象存储解决方案,提供与亚马逊云科技 S3 兼容的 API,并支持所有核心 S3 功能。MinIO 专为部署在任何地方而构建 - 公共云或私有云、裸机基础架构、编排环境和边缘基础架构。
二、Minio的基本概念
- Object:存储到MinIO的基本对象,即对文件的抽象。如文件,字节流等
- Bucket:存储Object的逻辑空间,每个Bucket之间的数据时相互隔离的。对于用户而言,相当于存放文件的顶层文件夹。
- Drive:存储Object的磁盘。在MinIO启动时,以参数的方式传入。
- Set:一组Drive的集合。根据集群规模自动划分Set,每个Set中的Drive分布在不同位置。
- EC:纠删码(Erasure Code),用来把丢失的数据进行恢复。
Minio存储文件时,会在对应的数据存储磁盘中,以Bucket名称为目录,文件名称为下一级目录,文件名下是xl.meta,通过奇偶的形式存储 编码数据块及检验块和元数据文件。
三、Docker安装Minio
1、拉去minio镜像
docker search minio
docker push 镜像名称
2、执行minio镜像具体可参考官网
docker run \
-p 9000:9000 \ #服务端端口
-p 9090:9090 \ #客户端端口
--name minio1 \ #容器名称
-v D:\ProjectSpace\data:/data \ #文件存放路径
-e "MINIO_ACCESS_KEY=admin" \ #管理平台账号
-e "MINIO_SECRET_KEY=admin123" \ #密码
quay.io/minio/minio server /data --console-address ":9090" #指定客户端端口
三、Spring Boot 整合 Minio
1、导入Minio依赖
<!--minio-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.0.3</version>
</dependency>
2、编写application.yml
spring:
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB
server:
port: 8090
minio:
endpoint: http://127.0.0.1:9000
accessKey: admin
secretKey: admin123
bucketName: picture
3、编写配置类
@Component
public class MinioClientConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
4、编写工具类
@Setter
@Getter
@AllArgsConstructor
public class CommonResult {
/**
* 状态码
*/
private int code;
/**
* 响应信息
*/
private String message;
/**
* 响应数据
*/
private Object data;
public static CommonResult success() {
return new CommonResult(200, "success", null);
}
public static CommonResult success(Object data) {
return new CommonResult(200, "success", data);
}
public static CommonResult fail(String message) {
return new CommonResult(400, message, null);
}
}
- 判断Bucket是否存在
@Autowired
private MinioClient minioClient;
/**
* Bucket是否存在
*
* @param bucketName
* @return
*/
public boolean bucketExisted(String bucketName) {
boolean isExist = false;
try {
isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception ex) {
log.info("bucketExisted error: {}", ex.getMessage());
return false;
}
return isExist;
}
- 创建Bucket
@Autowired
private MinioClient minioClient;
/**
* 创建Bucket
*
* @param bucketName
* @return
*/
public boolean createBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
} catch (Exception ex) {
log.info("createBucket error: {}", ex.getMessage());
return false;
}
return true;
}
- 删除Bucket
@Autowired
private MinioClient minioClient;
/**
* 删除Bucket
*
* @param bucketName
* @return
*/
public boolean deleteBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
} catch (Exception ex) {
log.info("deleteBucket error: {}", ex.getMessage());
return false;
}
return true;
}
- 获取所有Bucket
@Autowired
private MinioClient minioClient;
/**
* 获取所有Bucket
*
* @return
*/
public List<Bucket> getAllBuckets() {
List<Bucket> buckets = null;
try {
minioClient.listBuckets();
} catch (Exception ex) {
log.info("getAllBuckets error: {}", ex.getMessage());
}
return (buckets == null) ? new ArrayList<>() : buckets;
}
- 文件上传
@Autowired
private MinioClient minioClient;
/**
* 上传文件
*
* @param file
* @param bucketName
* @return 文件名
*/
public String uploadFile(MultipartFile file, String bucketName) {
String originalFilename = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
String objectName = simpleDateFormat.format(new Date()) + "_" + fileName;
try {
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType()).build();
minioClient.putObject(putObjectArgs);
} catch (Exception ex) {
log.info("uploadFile error: {}", ex.getMessage());
return null;
}
return objectName;
}
- 文件下载
@Autowired
private MinioClient minioClient;
/**
* 根据文件名下载文件
*
* @param fileName
* @param bucketName
* @param res
*/
public void download(String fileName, String bucketName, HttpServletResponse res) {
GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(bucketName).object(fileName).build();
FastByteArrayOutputStream os = null;
try (GetObjectResponse response = minioClient.getObject(getObjectArgs)) {
byte[] buf = new byte[1024];
int len;
os = new FastByteArrayOutputStream();
while ((len = response.read(buf)) != -1) {
os.write(buf, 0, len);
}
os.flush();
res.setCharacterEncoding("utf-8");
res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
try (ServletOutputStream outputStream = res.getOutputStream()) {
outputStream.write(os.toByteArray());
outputStream.flush();
}
} catch (Exception ex) {
log.info("download error: {}", ex.getMessage());
} finally {
os.close();
}
}
- 获取文件地址
@Autowired
private MinioClient minioClient;
/**
* 根据文件名获取文件地址
*
* @param fileName
* @param bucketName
* @return 文件地址
*/
public String preview(String fileName, String bucketName) {
try {
GetPresignedObjectUrlArgs presignedObjectUrlArgs = new GetPresignedObjectUrlArgs().builder()
.bucket(bucketName)
.object(fileName)
.method(Method.GET)
.build();
return minioClient.getPresignedObjectUrl(presignedObjectUrlArgs);
} catch (Exception ex) {
log.info("preview error: {}", ex.getMessage());
return null;
}
}
- 获取Bucket中所有Object
@Autowired
private MinioClient minioClient;
/**
* 获取Bucket中所有文件对象
*
* @param bucketName
* @return
*/
public List<Item> listObjects(String bucketName) {
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
List<Item> items = new ArrayList<>();
results.forEach(item -> {
try {
items.add(item.get());
} catch (Exception ex) {
log.info("listObjects error: {}", ex.getMessage());
}
});
return items;
}
- 删除文件
@Autowired
private MinioClient minioClient;
/**
* 删除文件
*
* @param fileName
* @param bucketName
* @return
*/
public boolean removeFile(String fileName, String bucketName) {
try {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
} catch (Exception ex) {
log.info("removeFile error: {}", ex.getMessage());
return false;
}
return true;
}
5、编写Service层和Controller层
FileService接口自行补充
@Slf4j
@Service
public class MinioFileServiceImpl implements FileService {
@Value("${minio.bucketName}")
private String bucketName;
@Autowired
private MinioUtils minioUtils;
@Override
public CommonResult upload(MultipartFile file) {
if (file.isEmpty()) {
return CommonResult.fail("文件不可为空");
}
String fileName = minioUtils.uploadFile(file, bucketName);
return CommonResult.success(fileName);
}
@Override
public void download(String fileName, HttpServletResponse res) {
ObjectMapper objectMapper = new ObjectMapper();
try(ServletOutputStream outputStream = res.getOutputStream()) {
if (StringUtils.isEmpty(fileName)) {
outputStream.write(objectMapper.writeValueAsBytes(CommonResult.fail("文件名不可为空")));
}
minioUtils.download(fileName, bucketName, res);
} catch (IOException ex) {
log.warn("download file error: {}", ex.getMessage());
}
}
@Override
public CommonResult delete(String fileName) {
if (StringUtils.isEmpty(fileName)) {
return CommonResult.fail("文件名不可为空");
}
minioUtils.removeFile(fileName, bucketName);
return CommonResult.success();
}
@Override
public CommonResult review(String fileName) {
if (StringUtils.isEmpty(fileName)) {
return CommonResult.fail("文件名不可为空");
}
String preview = minioUtils.preview(fileName, bucketName);
return CommonResult.success(preview);
}
}
@RequestMapping("/file")
@Controller
public class FileController {
@Autowired
private FileService fileService;
@ResponseBody
@PostMapping("/upload")
public CommonResult upload(MultipartFile file) {
return fileService.upload(file);
}
@PostMapping("/download")
public void download(@RequestParam("fileName") String fileName, HttpServletResponse res) {
fileService.download(fileName, res);
}
@ResponseBody
@PostMapping("/delete")
public CommonResult delete(@RequestParam("fileName") String fileName) {
return fileService.delete(fileName);
}
@ResponseBody
@PostMapping("/preview")
public CommonResult preview(@RequestParam("fileName") String fileName) {
return fileService.review(fileName);
}
}
转载自:https://juejin.cn/post/7245919919224422455