基本介绍
什么是 MinIO
MinIO 是一款基于 Go 语言的高性能、可扩展、云原生支持、操作简单、开源的分布式对象存储产品。基于 Apache License v2.0 开源协议,虽然轻量,却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应用结合使用,例如 NodeJS、Redis、MySQL 等。
MinIO 特点
docker 安装 minio
docker pull minio/minio
docker images
创建并启动minIO容器:
这里的9090端口指的是minio的客户端端口。虽然设置9090,但是我们在访问9000的时候,他也会自动跳到9090。
9000端口是minio的服务端端口,我们程序在连接minio的时候,就是通过这个端口来连接的。
-v就是docker run当中的挂载,这里的/usr/local/mydata/minio/data:/data意思就是将容器的/data目录和宿主机的/mydata/minio/data目录做映射,这样我们想要查看容器的文件的时候,就不需要看容器当中的文件了。
注意在执行命令的时候,他是会自动在宿主机当中创建目录的。我们不需要手动创建。
minio所上传的文件默认都是存储在容器的data目录下的!
假如删除容器了宿主机当中挂载的目录是不会删除的。假如没有使用-v挂载目录,那他在宿主机的存储位置的文件会直接删除的。
宿主机的挂载目录一定是根目录,如果是相对路径会有问题。还有容器当中的目录也是必须是绝对路径(根路径就是带/的)。
所谓的挂载其实就是将容器目录和宿主机目录进行绑定了,操作宿主机目录,容器目录也会变化,操作容器目录,宿主机目录也会变化。这样做的目的 可以间接理解为就是数据持久化,防止容器误删,导致数据丢失的情况。
MINIO_ACCESS_KEY:账号 MINIO_SECRET_KEY:密码 (正常账号应该不低于3位,密码不低于8位,不然容器会启动不成功)
–console-address 指定客户端端口
-d --restart=always 代表重启linux的时候容器自动启动
–name minio 容器名称
docker run -p 9000:9000 -p 9090:9090 --name minio -d --restart=always
-e "MINIO_ACCESS_KEY=minioadmin"
-e "MINIO_SECRET_KEY=minioadmin"-v /usr/local/mydata/minio/data:/data
minio/minio server /data --console-address ":9090" -address ":9000"
springboot集成minio
一、配置yml文件
- #yml配置文件增加如下配置
-
- minio:
- endpoint: http://ip:9000
- fileUploadUrl: http://ip:9000
- accessKey: minioadmin (用户名)
- secretKey: minioadmin (密码)
- bucketName: file (文件组:桶名)
二、引入pom(8与7的方法不适用,以下使用8.0.3)
-
- <groupId>io.miniogroupId>
- <artifactId>minioartifactId>
- <version>8.0.3version>
-
三、系统加载minio配置
- @Data
- @Configuration
- @ConfigurationProperties(prefix = "minio")
- public class MinioConfig {
-
- private String endpoint;
- private String accessKey;
- private String secretKey;
- private String bucketName;
-
- @Bean
- public MinioClient minioClient() {
- MinioClient minioClient = MinioClient.builder()
- .endpoint(endpoint)
- .credentials(accessKey, secretKey)
- .build();
- return minioClient;
- }
-
- }
四、minio工具类(上传文件,返回访问链接)
- package org;
-
- import cn.hutool.core.io.FastByteArrayOutputStream;
- import com.alibaba.fastjson.JSONObject;
- import io.minio.*;
- import io.minio.http.Method;
- import io.minio.messages.Bucket;
- import io.minio.messages.DeleteError;
- import io.minio.messages.DeleteObject;
- import io.minio.messages.Item;
- import org.springframework.stereotype.Component;
- import org.springframework.web.multipart.MultipartFile;
-
- import javax.annotation.Resource;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServletResponse;
- import java.io.InputStream;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.UUID;
- import java.util.stream.Collectors;
-
- /**
- * 功能描述 文件服务器工具类
- *
- * @author:
- * @date:
- */
- @Component
- public class MinioUtil {
-
- @Resource
- private MinioClient minioClient;
-
- /**
- * 查看存储bucket是否存在
- * @return boolean
- */
- public Boolean bucketExists(String bucketName) {
- Boolean found;
- try {
- found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
- } catch (Exception e) {
- //e.printStackTrace();
- return false;
- }
- return found;
- }
-
- /**
- * 创建存储bucket
- * @return Boolean
- */
- public Boolean makeBucket(String bucketName) {
- try {
- minioClient.makeBucket(MakeBucketArgs.builder()
- .bucket(bucketName)
- .build());
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
- /**
- * 删除存储bucket
- * @return Boolean
- */
- public Boolean removeBucket(String bucketName) {
- try {
- minioClient.removeBucket(RemoveBucketArgs.builder()
- .bucket(bucketName)
- .build());
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
- /**
- * 获取全部bucket
- */
- public List
getAllBuckets() { - try {
- return minioClient.listBuckets();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- /**
- * 文件上传
- * @param file 文件
- * @return Boolean
- */
- public Boolean upload(String bucketName, String fileName, MultipartFile file, InputStream inputStream) {
- try {
- PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName)
- .stream(inputStream,file.getSize(),-1).contentType(file.getContentType()).build();
- //文件名称相同会覆盖
- minioClient.putObject(objectArgs);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- /**
- * 预览图片
- * @param fileName
- * @return
- */
- public String preview(String fileName,String bucketName){
- // 查看文件地址
- GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(bucketName).object(fileName).method(Method.GET).build();
- try {
- String url = minioClient.getPresignedObjectUrl(build);
- return url;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- /**
- * 文件下载
- * @param fileName 文件名称
- * @param res response
- * @return Boolean
- */
- public void download(String fileName,String bucketName, HttpServletResponse res) {
- 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();
- res.setCharacterEncoding("utf-8");
- //设置强制下载不打开
- //res.setContentType("application/force-download");
- res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
- try (ServletOutputStream stream = res.getOutputStream()){
- stream.write(bytes);
- stream.flush();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 查看文件对象
- * @return 存储bucket内文件对象信息
- */
- public List
- listObjects(String bucketName) {
- Iterable
> results = minioClient.listObjects( - ListObjectsArgs.builder().bucket(bucketName).build());
- List
- items = new ArrayList<>();
- try {
- for (Result
- result : results) {
- items.add(result.get());
- }
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- return items;
- }
-
- /**
- * 删除
- * @param fileName
- * @return
- * @throws Exception
- */
- public boolean remove(String fileName,String bucketName){
- try {
- minioClient.removeObject( RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
- }catch (Exception e){
- return false;
- }
- return true;
- }
-
- /**
- * 批量删除文件对象(没测试)
- * @param objects 对象名称集合
- */
- public Iterable
> removeObjects(List objects, String bucketName) { - List
dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList()); - Iterable
> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build()); - return results;
- }
-
- //上传文件,返回路径
- public Object upload(HashMap
paramMap) { - MultipartFile file=(MultipartFile)paramMap.get("file");
- if (file.isEmpty() || file.getSize() == 0) {
- return "文件为空";
- }
- try {
- if (!this.bucketExists("file")) {
- this.makeBucket("file");
- }
- InputStream inputStream = file.getInputStream();
- String fileName = file.getOriginalFilename();
-
- String newName = UUID.randomUUID().toString().replaceAll("-", "")
- + fileName.substring(fileName.lastIndexOf("."));
-
- this.upload("file", newName,file, inputStream);
- inputStream.close();
- String fileUrl = this.preview(newName,"file");
- String fileUrlNew=fileUrl.substring(0, fileUrl.indexOf("?"));
- JSONObject jsonObject=new JSONObject();
- jsonObject.put("url",fileUrlNew);
- return jsonObject.toJSONString();
- } catch (Exception e) {
- e.printStackTrace();
- return "上传失败";
- }
- }
- }
项目中实践
永久存储方式:把bucket的权限设置为public,返回路径到文件名称