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 ...
随机推荐
- 【Spring Framework】Spring入门教程(七)Spring 事件
内置事件 Spring中的事件是一个ApplicationEvent类的子类,由实现ApplicationEventPublisherAware接口的类发送,实现ApplicationListener ...
- 【VSCode】检测到 #include 错误。请更新 includePath。已为此翻译单元(C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\i686-
win+r 运行cmd 输入"gcc -v -E -x c -"获取mingw路径: 我的: #include "..." search starts here ...
- 学Java,Java书籍的最佳阅读顺序
疫情以来,好久没出差了,今天出差去趟上海,早上 4 点多就起床了,到机场天都没亮.到登机口离起飞还一小时,趁着等飞机的时间,抓紧码字,把这篇文章收个尾. 今天和大家说说学 Java 的读书路线.路线中 ...
- Android App加固原理与技术历程
App为什么会被破解入侵 随着黑客技术的普及化平民化,App,这个承载我们移动数字工作和生活的重要工具,不仅是黑客眼中的肥肉,也获得更多网友的关注.百度一下"App破解"就有529 ...
- AtCoder Beginner Contest 184 题解
AtCoder Beginner Contest 184 题解 目录 AtCoder Beginner Contest 184 题解 A - Determinant B - Quizzes C - S ...
- [源码解析] PyTorch 分布式之弹性训练(1) --- 总体思路
[源码解析] PyTorch 分布式之弹性训练(1) --- 总体思路 目录 [源码解析] PyTorch 分布式之弹性训练(1) --- 总体思路 0x00 摘要 0x01 痛点 0x02 难点 0 ...
- CF450B Jzzhu and Sequences 题解
Content 有一个长度为 \(n\) 的数列 \(\{a_1,a_2,\dots,a_n\}\),满足如下的递推公式: \(i=1\) 时,\(a_1=x\). \(i=2\) 时,\(a_2=y ...
- java 多线程 线程组ThreadGroup;多线程的异常处理。interrupt批量停止组内线程;线程组异常处理
1,线程组定义: 线程组存在的意义,首要原因是安全.java默认创建的线程都是属于系统线程组,而同一个线程组的线程是可以相互修改对方的数据的.但如果在不同的线程组中,那么就不能"跨线程组&q ...
- redis pipeset发布订阅
#!/usr/bin/env python # Author:Zhangmingda import redis,time pool = redis.ConnectionPool(host='192.1 ...
- c++11之获取模板函数的参数个数和函数返回值类型
本文演示c++需要支持c++11及以上标准 获取参数个数 1.模板函数声明 template <class R, class... Args> R getRetValue(R(*)(Arg ...