minio文件上传与下载
一、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文件上传与下载的更多相关文章
- java web学习总结(二十四) -------------------Servlet文件上传和下载的实现
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- (转载)JavaWeb学习总结(五十)——文件上传和下载
源地址:http://www.cnblogs.com/xdp-gacl/p/4200090.html 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传 ...
- JavaWeb学习总结,文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- java文件上传和下载
简介 文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到 ...
- 使用jsp/servlet简单实现文件上传与下载
使用JSP/Servlet简单实现文件上传与下载 通过学习黑马jsp教学视频,我学会了使用jsp与servlet简单地实现web的文件的上传与下载,首先感谢黑马.好了,下面来简单了解如何通过使用 ...
- JavaWeb学习总结(五十)——文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- 文件上传和下载(可批量上传)——Spring(三)
在文件上传和下载(可批量上传)——Spring(二)的基础上,发现了文件下载时,只有在Chrome浏览器下文件名正常显示,还有发布到服务器后,不能上传到指定的文件夹目录,如上传20160310.txt ...
- 文件上传和下载(可批量上传)——Spring(二)
针对SpringMVC的文件上传和下载.下载用之前“文件上传和下载——基础(一)”的依然可以,但是上传功能要修改,这是因为springMVC 都为我们封装好成自己的文件对象了,转换的过程就在我们所配置 ...
- Struts2 之 实现文件上传和下载
Struts2 之 实现文件上传和下载 必须要引入的jar commons-fileupload-1.3.1.jar commons-io-2.2.jar 01.文件上传需要分别在struts.xm ...
随机推荐
- react中在hooks方法useEffect中加载异步数据
useEffect( ()=>{ (async function getPipeList(value:any) { let result= await GetPipeList(value); s ...
- 编译工具grdle部署
目录 一.简介 二.部署 三.测试 一.简介 Gradle 是以 Groovy 语言为基础,面向Java应用为主.基于DSL(领域特定语言)语法的自动化构建工具.在github上,gradle项目很多 ...
- ssm项目中常用的上传文件
在项目中,上传文件一般是必不可少的,所以今天学到新的上传方式,就干脆将学习过的上传方式记录一下 一.表单直接上传图片 表单头要设置 <form action="" metho ...
- CF1095B Array Stabilization 题解
Content 有一个长度为 \(n\) 的数组 \(a_1,a_2,a_3,...,a_n\),现在需要从这些数中删除一个数,使得 \(\max\limits_{i=1}^na_i-\min\lim ...
- urllib结合 concurrent.futures 多线程下载文件。
示例: #!/usr/bin/env python3 # -*- coding:utf-8 -*- # @Time: 2020/12/16 10:42 # @Author:zhangmingda # ...
- 缓存系统redis操作、mongdb、memeche
mongdb :默认数据持久化,存在内存的同时也向硬盘写数据. redis:可配置数据持久化,默认数据在内存中 memeche:only support 内存模式 redis操作 https://ww ...
- 分布式系统一致性算法(Paxos)
CAP理论 一致性(Consistency) 可用性(Availability) 分区容错性(网络分区)Partition toleranceCAP理论的特点,就是CAP只能满足其中 ...
- c++之快速排序改进(随机值)
数量少(5~25),插入排序很高效 一个影响快排效率的因素就是: 基准值的选择 本文将演示一种随之法的快排 改进前 void quick_sort5(int arr[], int low, int h ...
- LeetCode每日一题打卡组队监督!刷题群!
近 2000 人已经加入共同刷题啦! 群友每天都会在群里给大家讲解算法题 每周日「负雪明烛」组织直播讲题 我相信来看我博客的大部分人都是通过LeetCode刷题过来的.最近发现LeetCode中文网站 ...
- 【LeetCode】401. Binary Watch 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 java解法 Python解法 日期 [LeetCo ...