场景
若依前后端分离版手把手教你本地搭建环境并运行项目:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108465662
参考上面搭建项目。
Minio
Minio是基于Go语言编写的对象存储服务,适合于存储大容量非结构化的数据,例如图片、音频、视频、日志文件、备份数据和容器/虚拟机镜像等,
而一个对象文件可以是任意大小,从几kb到最大5T不等。区别于分布式存储系统,minio的特色在于简单、轻量级,对开发者友好。
特点
简单、可靠:
Minio采用简单可靠的集群方案,摒弃复杂的大规模的集群调度管理,减少风险与性能瓶颈,聚焦产品的核心功能,
打造高可用的集群、灵活的扩展能力以及超过的性能。建立众多的中小规模、易管理的集群,
支持跨数据中心将多个集群聚合成超大资源池,而非直接采用大规模、统一管理的分布式集群。
功能完善:
Minio支持云原生,能与Kubernetes、Docker、Swarm编排系统良好对接,实现灵活部署。
且部署简单,只有一个可执行文件,参数极少,一条命令即可启动一个Minio系统。
Minio为了高性能采取无元数据数据库设计,避免元数据库成为整个系统的性能瓶颈,
并将故障限制在单个集群之内,从而不会涉及其他集群。Minio同时完全兼容S3接口,
因此也可以作为网关使用,对外提供S3访问。同时使用Minio Erasure code和checksum 来防止硬件故障。
即使损失一半以上的硬盘,但是仍然可以从中恢复。分布式中也允许(N/2)-1个节点故障。
官方文档:
Java快速指南:
https://minio.org.cn/docs/minio/linux/developers/java/minio-java.html#minio-java-quickstart
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
实现
1、Minio在Windows上下载安装启动
https://www.minio.org.cn/download.shtml#/windows
下载之后只有一个minio.exe,然后新建一个文件存储路径,这里是D:\minioData
在minio.exe所在的目录下打开cmd,输入
minio.exe server D:\minioData后面跟着指定存储的目录
提示是因为未修改默认密码。
启动之后访问
这里会自动跳转到11466端口。
输入登录用户名密码,默认都为
minioadmin2、SpringBoot中整合Minio实现客户端
添加项目依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.2</version>
</dependency>
新增yml配置文件内容
minio:
server: http://127.0.0.1
port: 9000
accessKey:
minioadmin
secretKey: minioadmin
配置minio的ip、端口、用户名、密码
然后新建配置类,读取配置文件内容并建立minio连接
import io.minio.MinioClient;
import lombok.Data;
import
org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "minio")
@Data
public class MinioConfig{
private String server;
private int port;
private String accessKey;
private String secretKey;
/**
* 创建minio连接对象
* @return
*/
@Bean
public MinioClient
minioClient(){
return MinioClient.builder()
.endpoint(server,port,false)
.credentials(accessKey,secretKey)
.build();
}
}
3、SpringBoot中操作Minio的工具类和使用示例
Minio中使用Bucket桶的概念,类似文件目录,一般一个项目中使用一个桶。
新建Minio工具类
import cn.hutool.core.io.FastByteArrayOutputStream; import io.minio.*; import io.minio.http.Method; import io.minio.messages.Bucket; import io.minio.messages.Item; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; import java.util.UUID; @Component public class MinioUtils { @Autowired MinioClient minioClient; public final String PREFIX = "minio/"; /** * 查看存储bucket是否存在 * bucketName 需要传入桶名 * @return boolean */ public Boolean bucketExists(String bucketName) { Boolean found; try { found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } catch (Exception e) { e.printStackTrace(); return false; } return found; } /** * 创建存储bucket * bucketName 需要传入桶名 * @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 * bucketName 需要传入桶名 * @return Boolean */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 获取全部bucket */ public List<Bucket> getAllBuckets() { try { List<Bucket> buckets = minioClient.listBuckets(); return buckets; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 文件上传 * * @param file 文件 * @param bucketName bucketName * BucketName 需要传入桶名 * @return Boolean */ public String upload(String bucketName,MultipartFile file) { String originalFilename = file.getOriginalFilename(); if (StringUtils.isBlank(originalFilename)){ throw new RuntimeException(); } String fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf(".")); String objectName = PREFIX + fileName; try { PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(objectName) .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build(); //文件名称相同会覆盖 minioClient.putObject(objectArgs); } catch (Exception e) { e.printStackTrace(); return null; } return objectName; } /** * 预览 * @param fileName * @param bucketName bucketName * @return */ public String preview(String bucketName,String fileName){ // 查看文件地址 GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(bucketName).object(fileName).method(Method.GET).build(); try { String url = minioClient.getPresignedObjectUrl(build); return url; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 文件下载 * @param fileName 文件名称 * @param bucketName bucketName * @param res response * @return Boolean */ public void download(String bucketName,String fileName, HttpServletResponse res) { GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName) .object(fileName).build(); try (GetObjectResponse response = minioClient.getObject(objectArgs)){ byte[] buf = new byte[1024]; int len; try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){ while ((len=response.read(buf))!=-1){ os.write(buf,0,len); } os.flush(); byte[] bytes = os.toByteArray(); res.setCharacterEncoding("utf-8"); // 设置强制下载不打开 // res.setContentType("application/force-download"); res.addHeader("Content-Disposition", "attachment;fileName=" + fileName); try (ServletOutputStream stream = res.getOutputStream()){ stream.write(bytes); stream.flush(); } } } catch (Exception e) { e.printStackTrace(); } } /** * 查看文件对象 * @param bucketName bucketName * @return 存储bucket内文件对象信息 */ public List<Item> listObjects(String bucketName) { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build()); List<Item> items = new ArrayList<>(); try { for (Result<Item> result : results) { items.add(result.get()); } } catch (Exception e) { e.printStackTrace(); return null; } return items; } /** * 删除文件 * @param fileName * @param bucketName * @return * @throws Exception */ public boolean remove(String bucketName,String fileName){ try { minioClient.removeObject( RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build()); }catch (Exception e){ return false; } return true; } }
单元测试,引入工具类
@Autowiredprivate MinioUtils minioUtils;
测试新建桶
/**
* 创建存储bucket
*/
@Test
public void createBucke(){
List<Bucket> allBuckets =
minioUtils.getAllBuckets();
allBuckets.stream().forEach(bucket -> System.out.println(bucket.name()));
minioUtils.makeBucket("new");
allBuckets = minioUtils.getAllBuckets();
allBuckets.stream().forEach(bucket ->
System.out.println(bucket.name()));
}
测试获取全部桶
/*** 获取全部bucket
*/
@Test
public void getAllBuckets() {
List<Bucket> allBuckets = minioUtils.getAllBuckets();
System.out.println(allBuckets);
}
测试桶是否存在
/**
* 测试桶是否存在
*/
@Test
public void bucketExists() {
System.out.println(minioUtils.bucketExists("badao"));//true
System.out.println(minioUtils.bucketExists("test"));//false
}
测试移除桶
/*** 移除bucket
*/
@Test
public void removeBucke(){
List<Bucket> allBuckets = minioUtils.getAllBuckets();
allBuckets.stream().forEach(bucket -> System.out.println(bucket.name()));
minioUtils.removeBucket("new");
allBuckets = minioUtils.getAllBuckets();
allBuckets.stream().forEach(bucket -> System.out.println(bucket.name()));
}
测试文件上传,这里使用MockMultipartFile模拟文件
/**
* upload file
*/
@Test
public void upload(){
//MockmulpipartFile
//第一个参数是表单中文件上传的字段名
//第二个参数是文件名
//第三个参数是文件的MIME类型
//第四个参数是文件的内容
MultipartFile mockFile = new
MockMultipartFile("file","badao.txt","text/plain","File content".getBytes());
minioUtils.upload("badao",mockFile);
}
Java中MockMultipartFile使用来模拟文件的用法
MockmulpipartFile
第一个参数是表单中文件上传的字段名
第二个参数是文件名
第三个参数是文件的MIME类型
第四个参数是文件的内容
上传成功查看效果,可进行预览、下载等操作。
此时到minio的存储路径中也能看到文件
测试测试Minio预览
/**
* preview file
*/
@Test
public void preview(){
String prefix = minioUtils.PREFIX;
String preview
= minioUtils.preview("badao",
prefix+"cd6b22b2-55ce-41ea-ba6f-a9115e12a2fe.txt");
System.out.println(preview);
}
预览效果
测试Minio下载效果
import com.ruoyi.common.utils.MinioUtils;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.web.bind.annotation.GetMapping;
import
org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/test/minio")
public
class MinioTestController {
@Autowired
private
MinioUtils minioUtils;
@GetMapping("/download")
public void download(HttpServletResponse response) {
String prefix = minioUtils.PREFIX;
minioUtils.download("badao",prefix+"cd6b22b2-55ce-41ea-ba6f-a9115e12a2fe.txt",response);
}
}
请求接口测试效果
更多功能和使用参考官方文档说明。
标签:Minio,SpringBoot,return,minio,bucket,String,bucketName,import,分布式 From: https://www.cnblogs.com/badaoliumangqizhi/p/17995744