一、minio简介

MinIO 是在 GNU Affero 通用公共许可证 v3.0 下发布的高性能对象存储。 它是与 Amazon S3 云存储服务兼容的 API,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等

二、minio安装

参考我的另一篇文章:https://www.cnblogs.com/lvlinguang/p/15770479.html

一、java中使用

1、pom文件引用

<!-- minio 文件服务客户端 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>6.0.11</version>
</dependency>

2、添加配置文件

  • url:minio服务器的接口地址,不是访问地址
  • accessKey/secretKey:登录minio系统,新建Service Accounts
config:
minio:
url: http://192.168.3.15:9000
accessKey: 66SBZWYDSO0DZRSE1U3T
secretKey: S+p8mWE8aykZ0YsRtC0ef35qUS7fUbkITITJdjS6

3、注册MinioClient

@Data
@Configuration
@ConfigurationProperties(prefix = "config.minio")
public class MinioConfig {
/**
* minio 服务地址 http://ip:port
*/
private String url; /**
* 用户名
*/
private String accessKey; /**
* 密码
*/
private String secretKey; @SneakyThrows
@Bean
@RefreshScope
public MinioClient minioClient(){
return new MinioClient(url, accessKey, secretKey);
}
}

4、minio工具类

/**
* minio工具类
*
* @author lvlinguang
* @date 2022-01-07 12:26
* @see http://docs.minio.org.cn/docs/master/java-client-api-reference
*/
@Component
public class MinioUtils { @Autowired
private MinioClient client; /**
* 创建bucket
*
* @param bucketName
*/
@SneakyThrows
public void createBucket(String bucketName) {
if (!client.bucketExists(bucketName)) {
client.makeBucket(bucketName);
}
} /**
* 获取所有bucket
*
* @return
*/
@SneakyThrows
public List<Bucket> listAllBuckets() {
return client.listBuckets();
} /**
* bucket详情
*
* @param bucketName 名称
* @return
*/
@SneakyThrows
public Optional<Bucket> getBucket(String bucketName) {
return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
} /**
* 删除bucket
*
* @param bucketName 名称
*/
@SneakyThrows
public void removeBucket(String bucketName) {
client.removeBucket(bucketName);
} /**
* 上传文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @throws Exception
*/
@SneakyThrows
public void uploadFile(String bucketName, String objectName, InputStream stream) throws Exception {
this.uploadFile(bucketName, objectName, stream, (long) stream.available(), "application/octet-stream");
} /**
* 上传文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param size 大小
* @param contextType 类型
* @throws Exception
*/
@SneakyThrows
public void uploadFile(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
//如果bucket不存在,则创建
this.createBucket(bucketName);
client.putObject(bucketName, objectName, stream, size, null, null, contextType);
} /**
* 获取文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @return
*/
@SneakyThrows
public InputStream getFile(String bucketName, String objectName) {
return client.getObject(bucketName, objectName);
} /**
* 根据文件前置查询文件
*
* @param bucketName bucket名称
* @param prefix 前缀
* @param recursive 是否递归查询
* @return
*/
@SneakyThrows
public List<MinioItem> listAllFileByPrefix(String bucketName, String prefix, boolean recursive) {
List<MinioItem> objectList = new ArrayList<>();
Iterable<Result<Item>> objectsIterator = client
.listObjects(bucketName, prefix, recursive);
while (objectsIterator.iterator().hasNext()) {
objectList.add(new MinioItem(objectsIterator.iterator().next().get()));
}
return objectList;
} /**
* 删除文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
*/
@SneakyThrows
public void removeFile(String bucketName, String objectName) {
client.removeObject(bucketName, objectName);
} /**
* 获取文件外链
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param expires 过期时间 <=7
* @return
*/
@SneakyThrows
public String getFileURL(String bucketName, String objectName, Integer expires) {
return client.presignedGetObject(bucketName, objectName, expires);
} /**
* 获取文件信息
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @return
*/
@SneakyThrows
public ObjectStat getFileInfo(String bucketName, String objectName) {
return client.statObject(bucketName, objectName);
}
}

5、文件操作类

/**
* 系统文件工具类
*
* @author lvlinguang
* @date 2021-02-28 12:30
*/
@Component
public class SysFileUtils { /**
* 文件服务器中的目录分隔符
*/
public static final String SEPRETOR = "/"; @Autowired
private MinioUtils minioUtils; /**
* 文件上传
*
* @param object 文件对你
* @param bucketName bucket名称
* @return
*/
@SneakyThrows
public MinioObject uploadFile(MultipartFile object, String bucketName) {
return this.uploadFile(object.getInputStream(), bucketName, object.getOriginalFilename());
} /**
* 文件上传
*
* @param object 文件对你
* @param bucketName bucket名称
* @param fileName 文件名
* @return
*/
@SneakyThrows
public MinioObject uploadFile(MultipartFile object, String bucketName, String fileName) {
return this.uploadFile(object.getInputStream(), bucketName, fileName);
} /**
* 文件上传
*
* @param object 文件对你
* @param bucketName bucket名称
* @param randomFileName 文件名是否随机(是:按年/月/日/随机值储存,否:按原文件名储存)
* @return
*/
@SneakyThrows
public MinioObject uploadFile(MultipartFile object, String bucketName, Boolean randomFileName) {
//文件名
String fileName = object.getOriginalFilename();
if (randomFileName) {
//扩展名
String extName = FileUtil.extName(object.getOriginalFilename());
if (StrUtil.isNotBlank(extName)) {
extName = StrUtil.DOT + extName;
}
//新文件名
fileName = randomFileName(extName);
}
return this.uploadFile(object.getInputStream(), bucketName, fileName);
} /**
* 文件上传
*
* @param object 文件对你
* @param bucketName bucket名称
* @param fileName 文件名
* @return
*/
@SneakyThrows
public MinioObject uploadFile(InputStream object, String bucketName, String fileName) {
try {
minioUtils.uploadFile(bucketName, fileName, object);
return new MinioObject(minioUtils.getFileInfo(bucketName, fileName));
} catch (Exception e) {
throw new Exception(e);
} finally {
if (object != null) {
object.close();
}
}
} /**
* 下载文件
*
* @param response response
* @param url 文件地址(/bucketName/fileName)
*/
public void downloadFile(HttpServletResponse response, String url) {
final String bucketName = getBucketName(url);
final String filePath = getFilePath(url);
this.downloadFile(response, bucketName, filePath);
} /**
* 下载文件
*
* @param response response
* @param bucket bucket名称
* @param fileName 文件名
*/
public void downloadFile(HttpServletResponse response, String bucket, String fileName) {
try (InputStream inputStream = minioUtils.getFile(bucket, fileName)) {
if ("jpg".equals(FileUtil.extName(fileName))) {
response.setContentType("image/jpeg");
} else if ("png".equals(FileUtil.extName(fileName))) {
response.setContentType("image/png");
} else {
response.setContentType("application/octet-stream; charset=UTF-8");
}
IoUtil.copy(inputStream, response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
} /**
* 获取链接地址的 文件名
*
* @param bucketFileUrl
* @return
*/
public static String getFilePath(String bucketFileUrl) {
if (bucketFileUrl == null) {
return null;
}
//去掉第一个分割符
if (bucketFileUrl.startsWith(SEPRETOR)) {
bucketFileUrl = bucketFileUrl.substring(1);
}
return bucketFileUrl.substring(bucketFileUrl.indexOf(SEPRETOR) + 1);
} /**
* 获取链接地址的 bucketName
*
* @param bucketFileUrl 地址(/{bucketName}/{path}/{fileName})
* @return
*/
public static String getBucketName(String bucketFileUrl) {
if (bucketFileUrl == null) {
return null;
}
//去掉第一个分割符
if (bucketFileUrl.startsWith(SEPRETOR)) {
bucketFileUrl = bucketFileUrl.substring(1);
}
return bucketFileUrl.substring(0, bucketFileUrl.indexOf(SEPRETOR));
} /**
* 生成新的文件名
*
* @param extName 扩展名
* @return
*/
public static String randomFileName(String extName) {
LocalDate now = LocalDate.now();
return now.getYear() + SEPRETOR +
getFullNumber(now.getMonthValue()) + SEPRETOR +
getFullNumber(now.getDayOfMonth()) + SEPRETOR +
UUID.randomUUID().toString().replace("-", "") + extName;
} /**
* 得到数字全称,带0
*
* @param number
* @return
*/
public static String getFullNumber(Integer number) {
if (number < 10) {
return "0" + number;
}
return number.toString();
}
}

5、返回包装类

@Data
public class MinioItem { private String objectName;
private Date lastModified;
private String etag;
private Long size;
private String storageClass;
private Owner owner;
private String type; public MinioItem(Item item) {
this.objectName = item.objectName();
this.lastModified = item.lastModified();
this.etag = item.etag();
this.size = (long) item.size();
this.storageClass = item.storageClass();
this.owner = item.owner();
this.type = item.isDir() ? "directory" : "file";
}
} @Data
public class MinioObject { private String bucketName;
private String name;
private Date createdTime;
private Long length;
private String etag;
private String contentType; public MinioObject(ObjectStat os) {
this.bucketName = os.bucketName();
this.name = os.name();
this.createdTime = os.createdTime();
this.length = os.length();
this.etag = os.etag();
this.contentType = os.contentType();
}
}

6、控制器调用

@RestController
@RequestMapping("/file")
public class FileController { public static final String MAPPING = "/file"; @Autowired
private SysFileUtils sysFileUtils; @PostMapping("/upload")
public ApiResponse<MinioObject> upload(@RequestPart("file") MultipartFile file, @RequestParam("bucketName") String bucketName) {
final MinioObject minioObject = sysFileUtils.uploadFile(file, bucketName, true);
return ApiResponse.ok(minioObject);
} @GetMapping("/info/**")
public void getFile(HttpServletRequest request, HttpServletResponse response) {
final String uri = request.getRequestURI();
String fullName = uri.replace(MAPPING + "/info", "");
sysFileUtils.downloadFile(response, fullName);
}
}

7、访问测试

  • 上传测试

-下载/访问测试

地址:http://192.168.3.15:30061/info/avatar/2022/01/07/41aaeb9f56e64c10971b2d9c675ce8fe.jpg

minio文件上传与下载的更多相关文章

  1. java web学习总结(二十四) -------------------Servlet文件上传和下载的实现

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  2. (转载)JavaWeb学习总结(五十)——文件上传和下载

    源地址:http://www.cnblogs.com/xdp-gacl/p/4200090.html 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传 ...

  3. JavaWeb学习总结,文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  4. java文件上传和下载

    简介 文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到 ...

  5. 使用jsp/servlet简单实现文件上传与下载

    使用JSP/Servlet简单实现文件上传与下载    通过学习黑马jsp教学视频,我学会了使用jsp与servlet简单地实现web的文件的上传与下载,首先感谢黑马.好了,下面来简单了解如何通过使用 ...

  6. JavaWeb学习总结(五十)——文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  7. 文件上传和下载(可批量上传)——Spring(三)

    在文件上传和下载(可批量上传)——Spring(二)的基础上,发现了文件下载时,只有在Chrome浏览器下文件名正常显示,还有发布到服务器后,不能上传到指定的文件夹目录,如上传20160310.txt ...

  8. 文件上传和下载(可批量上传)——Spring(二)

    针对SpringMVC的文件上传和下载.下载用之前“文件上传和下载——基础(一)”的依然可以,但是上传功能要修改,这是因为springMVC 都为我们封装好成自己的文件对象了,转换的过程就在我们所配置 ...

  9. Struts2 之 实现文件上传和下载

    Struts2  之 实现文件上传和下载 必须要引入的jar commons-fileupload-1.3.1.jar commons-io-2.2.jar 01.文件上传需要分别在struts.xm ...

随机推荐

  1. kubeadm安装k8s集群

    安装kubeadm kubectl kubelet 对于Ubuntu/debian系统,添加阿里云k8s仓库key,非root用户需要加sudo apt-get update && a ...

  2. Excel字符串函数公式大全

    一.Excel字符串的操作  1.1.Excel根据字节截取对应字符串(注:一个中文汉字对应两个字节) =LEFTB(A3,7) 从左边开始截取7个字节 =RIGHTB(A10,10) 从右边开始截取 ...

  3. 分布式可扩展web体系结构设计实例分析

    Web分布式系统设计准则 下面以一个上传和查询图片的例子来说明分布式web结构的设计考虑和常用的提高性能的方法.该例子提供上传图片和下载图片两个简单功能,并且有一下假设条件?: - 可以存储无上限数量 ...

  4. 统计图—柱状图可视化(python)

    # 柱状图 import matplotlib.pyplot as plt import matplotlib as mpl mpl.rcParams['font.sans-serif']=['Fan ...

  5. 解决Tomcat10.0.12源码编译问题进而剖析其优秀分层设计架构

    概述 Tomcat.Jetty.Undertow这几个都是非常有名实现Servlet规范的应用服务器,Tomcat本身也是业界上非常优秀的中间件,简单可将Tomcat看成是一个Http服务器+Serv ...

  6. CF289B Polo the Penguin and Matrix 题解

    Content 有一个 \(n\times m\) 的矩阵 \(A\),每次操作你可以将某一个元素增加或减少 \(d\),求是所有元素相等的最小操作次数,或者不存在这样的操作方案. 数据范围:\(1\ ...

  7. Amazing!!CSS 也能实现极光?

    在上次写完这篇文章 -- 巧用渐变实现高级感拉满的背景光动画 之后,文章下面的评论有同学留言,使用 CSS 可以实现极光吗? 像是这样: emmm,这有点难为人了.不过,最近我也尝试着去试了下,虽然不 ...

  8. More Effective C++ 基础议题(条款1-4)总结

    More Effective C++ 基础议题(条款1-4)总结 条款1:仔细区别pointers和references 如果有一个变量,其目的是用来指向(代表)另一个对象,但是也有可能它不指向(代表 ...

  9. SQL:利用多表更新优化子查询

    原SQL: update bi_data.order_list_wxset is_start='1',proc_time=now()where 1=1and is_end='0' and 交易时间&l ...

  10. windows平台使用 pthreads库

    note 近日封装一些跨平台库时, 发现线程的创建需要做平台的区分, windows的线程创建和Linux下的线程操作不一样.很麻烦,还要做平台区分. 能否在windows上使用pthread的线程库 ...