最近的项目中因为需要做一些上传和下载的工作,所以选择了minio。当然这也是公司的选择,废话不多说,今天主要是记录下经验。
中文网站:MinIO | 高性能,对Kubernetes友好的对象存储
你懂得,去掉cn 就是官方网站。在官方网站上有你要的信息。不打开看看吗?看起来了不起的样子
MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。
MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。
MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。
在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品
1、数据安全
分布式存储,保证数据安全
2、高可用
分布式多副本机制,可以保证服务的高可用,即使挂掉几个也能保证服务
3、一致性
互联网非结构化数据的存储需求
懒省事,直接选择docker部署,看下脚本吧,没啥问题。
- docker run -p 9000:9000 --net=host \
- --name minio1 \
- -d \
- -e MINIO_ACCESS_KEY=minio \
- -e MINIO_SECRET_KEY=minio@123 \
- -v /home/docker/minio/data:/data \
- -v /home/docker/minio/config:/root/.minio \
- minio/minio server /data
启动起来登录进控制台
管理地址:http://172.26.1.152:9000/,用户名和地址在上面的脚本里
这里在线上直接找了一个,你可以在repo里查找最新的
- <dependency>
- <groupId>io.miniogroupId>
- <artifactId>minioartifactId>
- <version>8.0.0version>
- dependency>
application.yml,这里直接创建了一个配置,你可以根据自己的需求定义格式
- minio:
- endpoint: http://172.26.1.152:9000 # endpoint
- accessKey: minio #用户名
- secretKey: minio@123 # 密码
- bucketName: apply # bucketName
这里使用了lombok,如果你没使用的话,可以去除data注解,然后创建一些get/set方法。
- 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;
-
- @Data
- @Configuration
- @ConfigurationProperties(prefix = "minio")
- public class MinioConfig {
- private String endpoint;
- private String accessKey;
- private String secretKey;
- @Bean
- public MinioClient minioClient() {
- MinioClient minioClient = MinioClient.builder()
- .endpoint(endpoint)
- .credentials(accessKey, secretKey)
- .build();
- return minioClient;
- }
- }
这里借鉴了一些线上的文档,然后加了一些修改,可以直接拷贝到项目中使用。
- package com.xin.miniodemo.config;
-
- import io.minio.*;
- import io.minio.messages.Bucket;
- import io.minio.messages.DeleteError;
- import io.minio.messages.DeleteObject;
- import io.minio.messages.Item;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import org.springframework.util.FastByteArrayOutputStream;
- 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.stream.Collectors;
-
- /**
- * minio 工具类
- */
- @Component
- @Slf4j
- public class MinioUtil {
- @Autowired
- private MinioClient minioClient;
-
- /**
- * 查看存储bucket是否存在
- *
- * @return boolean
- */
- public boolean bucketExists(String bucketName) {
- boolean found = false;
- try {
- BucketExistsArgs args = BucketExistsArgs.builder().bucket(bucketName)
- .build();
- found = minioClient.bucketExists(args);
- } catch (Exception e) {
- log.error("bucketExists ", e);
- }
- return found;
- }
-
- /**
- * 创建存储bucket
- *
- * @return Boolean
- */
- public boolean makeBucket(String bucketName) {
- try {
- MakeBucketArgs makeArgs = MakeBucketArgs.builder()
- .bucket(bucketName)
- .build();
- minioClient.makeBucket(makeArgs);
- } catch (Exception e) {
- log.error("makeBucket ", e);
- return false;
- }
- return true;
- }
-
- /**
- * 删除存储bucket
- *
- * @return Boolean
- */
- public boolean removeBucket(String bucketName) {
- try {
- RemoveBucketArgs removeArgs = RemoveBucketArgs.builder()
- .bucket(bucketName)
- .build();
- minioClient.removeBucket(removeArgs);
- } catch (Exception e) {
- log.error("removeBucket ", e);
- return false;
- }
- return true;
- }
-
- /**
- * 获取全部bucket
- */
- public List
getAllBuckets() { - try {
- return minioClient.listBuckets();
- } catch (Exception e) {
- log.error("getAllBuckets ", e);
- }
- return null;
- }
-
- /**
- * 文件上传
- *
- * @param bucketName
- * @param fileName 上传文件的路径和名字
- * @param file
- * @return
- */
- public boolean upload(String bucketName, String fileName, MultipartFile file) {
- try {
- PutObjectArgs objectArgs = PutObjectArgs.builder()
- .bucket(bucketName)
- .object(fileName)
- .stream(file.getInputStream(), file.getSize(), -1)
- .contentType(file.getContentType())
- .build();
- //文件名称相同会覆盖
- minioClient.putObject(objectArgs);
- } catch (Exception e) {
- log.error("upload ", e);
- return false;
- }
- return true;
- }
-
-
- /**
- * 文件下载
- *
- * @param fileName 文件的路径和名字
- * @return Boolean
- */
- public void download(String fileName, String saveName, String bucketName) {
- DownloadObjectArgs build = DownloadObjectArgs.builder()
- .bucket(bucketName)
- .filename(saveName)
- .object(fileName)
- .build();
- try {
- minioClient.downloadObject(build);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * web下载文件
- *
- * @param fileName 文件的路径和名字
- * @param bucketName
- * @param resp
- */
- public void webDownload(String fileName, String bucketName, HttpServletResponse resp) {
- 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();
- resp.setCharacterEncoding("utf-8");
- //设置强制下载不打开
- //res.setContentType("application/force-download");
- resp.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
- try (ServletOutputStream stream = resp.getOutputStream()) {
- stream.write(bytes);
- stream.flush();
- }
- }
- } catch (Exception e) {
- log.error("webDownload ", e);
- }
- }
-
- /**
- * 查看文件对象
- *
- * @return 存储bucket内文件对象信息
- */
- public List
- listObjects(String bucketName) {
- ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder()
- .bucket(bucketName)
- .build();
- Iterable
> results = minioClient.listObjects(listObjectsArgs); - List
- itemList = new ArrayList<>();
- try {
- for (Result
- result : results) {
- itemList.add(result.get());
- }
- } catch (Exception e) {
- log.error("listObjects ", e);
- return null;
- }
- return itemList;
- }
-
- /**
- * 删除
- *
- * @param fileName
- * @return
- * @throws Exception
- */
- public boolean removeOne(String fileName, String bucketName) {
- try {
- RemoveObjectArgs removeArgs = RemoveObjectArgs.builder()
- .bucket(bucketName)
- .object(fileName)
- .build();
- minioClient.removeObject(removeArgs);
- } catch (Exception e) {
- log.error("remove ", e);
- return false;
- }
- return true;
- }
-
- /**
- * 批量删除文件对象
- *
- * @param objects 对象名称集合
- */
- public Iterable
> removeObjects(List objects, String bucketName) { - List
dos = objects.stream().map(DeleteObject::new).collect(Collectors.toList()); - RemoveObjectsArgs build = RemoveObjectsArgs.builder()
- .bucket(bucketName)
- .objects(dos)
- .build();
- Iterable
> results = minioClient.removeObjects(build); - return results;
- }
- }
-
-
这里直接创建了一个controller测试
- import com.xin.miniodemo.config.MinioUtil;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import org.springframework.web.multipart.MultipartFile;
-
- import javax.servlet.http.HttpServletResponse;
- import java.util.Arrays;
- import java.util.List;
-
- @RestController
- @RequestMapping
- public class TestController {
- @Autowired
- private MinioUtil minioUtil;
- @PostMapping("/upload")
- public String test(MultipartFile file) {
- minioUtil.upload("chongxin",file.getOriginalFilename(),file);
- return "Hello";
- }
- @PostMapping("/delete")
- public String delete(String fileName) {
- String[] fileArr = fileName.split(",");
- List
fl = Arrays.asList(fileArr); - minioUtil.removeObjects(fl,"chongxin");
- return "Hello";
- }
- @PostMapping("/download")
- public String download(String fileName) {
-
- minioUtil.download(fileName,"chongxin.jpg","chongxin.jpg");
- return "Hello";
- }
- @PostMapping("/webdownload")
- public String download(String fileName, HttpServletResponse response) {
-
- minioUtil.webDownload(fileName,"chongxin",response);
- return "Hello";
- }
- }
在开发的过程中还是出现一些问题的,但是已经都解决了,没有及时记录问题,这个有点可惜。
撸代码的时间还是快乐的,特别是解决问题之后,很开心
你的点赞是我分享的动力,欢迎点赞评论分享