使用minio进行文件上传
阿里云OSS解释:
对象存储服务OSS(Object Storage Service)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
对象存储最大的优势就在于它可以存储大容量的非结构化数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。对于大多数的企业来说,这可以说是最为理想的存储媒介了。
对于业务已在公有云上的企业来说,使用公有云提供的 OSS 服务,可以很好的节省存储的成本,且一般都提供易接入的 SDK,以阿里云的OSS 服务为例,在存储介质的上层封装可标注的 RESTful API 接口,使用起来十分方便。
但是对于一些没有选择业务上云或者想要下云的企业来说,要使用公有云的 OSS,在公网带宽方面就需要有一定的投入,毕竟需要通过公网传输,带宽太小,传输速度就会慢,且在传输过程中数据的安全性和完整性也有损失的风险,走专线的费用又十分昂贵,不实在。
这种情况下,MinIO 就是一个不错的选择,麻雀虽小,五脏俱全,企业可以以此快速构建自己内部的对象存储服务。(可以简单的认为MinIO就是一个远程的硬盘(存储数据))
Minio 是个基于 Golang 编写的开源对象存储套件,基于Apache License v2.0开源协议,虽然轻量,却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应用结合使用,例如 NodeJS、Redis、MySQL等。
它由桶(bucket,对应Windows下的文件夹),组成目录结构,桶中直接存放对象(Object,对应Windwos下的文件),桶中不能再创建通,但是要能创建文件夹 。
1. 高性能:
作为一款高性能存储,在标准硬件条件下,其读写速率分别可以达到 55Gb/s 和 35Gb/s。并而 MinIO 支持一个对象文件可以是任意大小,从几kb到最大5T不等。
2.可扩展:
不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并且支持跨越多个数据中心。
3.云原生:
容器化、基于K8S的编排、多租户支持。
4.Amazon S3兼容:
使用 Amazon S3 v2 / v4 API。可以使用Minio SDK,Minio Client,AWS SDK 和 AWS CLI 访问Minio服务器。
5.可对接多种后端存储:
除了Minio自己的文件系统,还支持 DAS、 JBODs、NAS、Google云存储和 Azure Blob存储。
6.SDK支持:
GO SDK: https://github.com/minio/minio-go
JavaSDK: https://github.com/minio/minio-java
PythonSDK: https://github.com/minio/minio-py
7.Lambda计算:
Minio服务器通过其兼容AWS SNS / SQS的事件通知服务触发Lambda功能。支持的目标是消息队列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等数据库。
8.图形化界面
有操作页面。
9.功能简单:
不容易出错,快速启动。
10.支持纠删码:
MinIO使用纠删码、Checksum来防止硬件错误和静默数据污染。在最高冗余度配置下,即使丢失1/2的磁盘也能恢复数据。
1、下载minio(官网下载:https://docs.min.io/)
2、将MinIO.exe 拷贝到自己的目录下去,并创建一个data目录
3、通过命令行启动Minio : minio server ./dta
4、启动完成后,可以看到访问的路径http://127.0.0.1:9000 (浏览器中打开)
。。。(在页面中创建桶就可以了)
io.minio
minio
7.0.2
# Miniio配置
minio:
endpoint: 127.0.0.1 #ip地址
port: 9000 # 端口号
accessKey: minioadmin # 账号
secretKey: minioadmin # 密码
secure: false #如果是true,则用的是https而不是http,默认值是true
bucketName: "huike-crm" # 桶的名字
configDir: "/data/excel" #保存到本地的路径
/**
* 文件上传至Minio
* 使用try catch finally进行上传
* finally里进行资源的回收
*/
@Override
public AjaxResult upload(MultipartFile file) {
InputStream inputStream = null;
//创建Minio的连接对象
MinioClient minioClient = getClient();
//桶对象
String bucketName = minioConfig.getBucketName();
try {
inputStream = file.getInputStream();
//基于官网的内容,判断文件存储的桶是否存在 如果桶不存在就创建桶
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().build());
if (exists) {
System.out.println("该桶已经存在");
} else {
minioClient.makeBucket(MakeBucketArgs.builder().build());
}
/**
* ================================操作文件================================
* 思路:我们上传的文件是:文件.pdf
* 那么我们应该上传到配置的bucket内 我们配置的bucketName是huike-crm
* 那么我们存在桶里的文件应该是什么样的 也叫“文件.pdf”吗?
* 应该按照上传的年月日进行区分
* 举例:2021-05-05日进行上传的
* 那么存在桶里的路径应该是
* huike-crm/2021/05/05/这个目录下
* 而对于同一个文件,存在重名问题,所以我们应该利用UUID生成一个新的文件名,并拼接上 .pdf 作为文件后缀
* 那么完整的路径就是 huike-crm/2021/05/05/uuid.pdf
*
* 如果上述思路你无法理解,那么就直接存放在桶内生成uuid+.pdf即可
* 即:huike-crm/uuid.pdf
*/
//操作文件
String fileName = file.getOriginalFilename();
String objectName = new SimpleDateFormat("yyyy/MM/dd/").format(new Date()) + UUID.randomUUID().toString().replaceAll("-", "")
+ fileName.substring(fileName.lastIndexOf("."));
PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName)
.bucket(bucketName)
.contentType(file.getContentType())
.stream(file.getInputStream(), file.getSize(), -1).build();
minioClient.putObject(objectArgs);
//封装访问的url给前端
AjaxResult ajax = AjaxResult.success();
ajax.put("fileName", "/" + bucketName + "/" + objectName);
//url需要进行截取
ajax.put("url", minioConfig.getEndpoint() + ":" + minioConfig.getPort() + "/" + minioConfig.getBucketName() + "/" + fileName);
/**
* 构建返回结果集
*/
/**
* 封装需要的数据进行返回
*/
return ajax;
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error("上传失败");
} finally {
//防止内存泄漏
if (inputStream != null) {
try {
inputStream.close(); // 关闭流
} catch (IOException e) {
log.debug("inputStream close IOException:" + e.getMessage());
}
}
}
}
//这个方法里面的属性用了一个配置文件实体类(minioConfig)(也就是一些minio的连接属性)
//属性自己看文档定义
/**
* 免费提供一个获取Minio连接的方法
* 获取Minio连接
* @return
*/
private MinioClient getClient() {
MinioClient minioClient =
MinioClient.builder()
.endpoint("http://" + minioConfig.getEndpoint() + ":" + minioConfig.getPort())
.credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
.build();
return minioClient;
}