如果您看着CSDN格式觉得不舒服,可以移步我的语雀该篇文章:

《minIO》https://www.yuque.com/docs/share/d9cd6a86-da8a-41b3-af56-6f357fad96cb?#%20%E3%80%8AminIO%E3%80%8B

目录

1、安装

1.1、Linux安装

1.2、Docker安装

1.3、Docker纠删码模式安装

1.4、分布式集群安装

2、代码实现

3、使用MinIO


1、安装

  • MinIO英文官网地址:MinIO High Performance Object Storage — MinIO Object Storage for Kubernetes
  • MinIO中文官网地址:MinIO Quickstart Guide| Minio中文文档

安装请按照英文官网,中文官网更新不及时。或者看我也可以!

1.1、Linux安装

1、先新建个你喜欢的目录,例如:mkdir -p /usr/local/minio

2、执行:wget https://dl.min.io/server/minio/release/darwin-amd64/minio

3、给文件夹赋权:chmod +x minio

PS:正常的目录应该是白色,赋权后应该是绿色,反正不是白色就对了

4、可以运行了:./minio /xxxxxxxxx/data

PS:启动minio server服务,指定数据存储目录/xxxxxxxxx/data

5、启动成功后,会出现红色Warning,不要慌

它的大概意思是告诉你:

一、这种方式启动,端口是随机的,下次再启动minIO端口就不一定是啥了

二、建议你用别的用户名,密码

解决:

一、添加用户名密码到环境变量:

export MINIO_ROOT_USER=admin

export MINIO_ROOT_PASSWORD=12345678

PS:长度要在8位以上,至于为啥,往后看

二、指定端口号启动:

./minio server --console-address ":50000" /xxxxxxxxx/data

PS:相较于第四步多了--console-address指定端口号启动

6、访问:http://xxxxx:50000/dashboard

1.2、Docker安装

1、新建挂载数据卷目录,例如:/mydata/minio/data/mydata/minio/config

2、拉取镜像:docker pull minio/minio

3、运行镜像

docker run -d -p 9000:9000 -p 50000:50000 --name minio \-v /mydata/minio/data:/data \-v /mydata/minio/config:/root/.minio \-e "MINIO_ROOT_USER=admin" \-e "MINIO_ROOT_PASSWORD=123456789" \minio/minio server --console-address ":50000" /data

解释为什么密码长度要最短8位,这里分享下我遇见的故障:

第一次运行的时候,也是使用-d后台运行,镜像启动之后,执行docker ps -a命令,看不到minio的运行端口号,执行docker ps命令查看镜像启动失败。

所以我使用控制台输出信息方式运行镜像(就是去掉-d命令)

它是告诉我,密码最少是8位。。。。

总结!!!以小窥大,告诉我们要养成看日志的习惯

4、访问:IP+端口号

1.3、Docker纠删码模式安装

docker run -d -p 9000:9000 -p 50000:50000 --name minio \
-v /mydata/minio/data1:/data1 \
-v /mydata/minio/data2:/data2 \
-v /mydata/minio/data3:/data3 \
-v /mydata/minio/data:/data4 \
-v /mydata/minio/data5:/data5 \
-v /mydata/minio/data:/data6 \
-v /mydata/minio/data7:/data7 \
-v /mydata/minio/data8:/data8 \
minio/minio server /data{1...8} --console-address ":50000"

1.4、分布式集群安装

自行百度吧,我买的腾讯云现成的。。。

2、代码实现

建议您呢,新建一个Spring Boot工程,复制下面我的代码,代码很简单,吸收了之后,再运用到你的项目

config:

package com.greedy.minio.config;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;/*** @Author: Greedy* @Date: Created in:2022-09-15* Description:*/
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {/*** 对象存储服务的 URL*/private String endpoint;/*** 用户名*/private String accessKey;/*** 密码*/private String secretKey;/*** 存储桶名称*/private String bucketName;/*** 预览到期时间(小时)*/private Integer previewExpiry;@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}
}

controller:

package com.greedy.minio.controller;import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.greedy.minio.pojo.FileUploadBody;
import com.greedy.minio.service.MinioService;
import com.greedy.minio.utils.Msg;
import com.greedy.minio.vo.FileVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletResponse;
import java.util.List;/*** @Author: Greedy* @Date: Created in:2022-09-15* Description:*/
@RestController
@Slf4j
public class MinioController {private final MinioService minioService;public MinioController(MinioService minioService) {this.minioService = minioService;}/*** 上传文件** @param body* @return*/@PostMapping("/upload")public Msg upload(FileUploadBody body) {List<FileVo> list = null;if (ObjUtil.isNull(body.getFiles())) {return Msg.ERROR.setNewMsg("上传文件不能为空");}try {list = minioService.uploadFile(body);log.info("文件上传成功,文件名称:{},bucket名称:{}", body.getFileName(), body.getBucket());} catch (Exception e) {log.error("文件上传失败,文件名称:{},bucket名称:{},错误信息:", body.getFileName(), body.getBucket(), e);return Msg.UPLOAD_ERROR;}return Msg.UPLOAD_SUCCESS.setNewData(list);}/*** 获取预览地址** @param fileName   文件名* @param bucketName 桶名* @return*/@GetMapping("/getPreviewUrl")public Msg getPreviewUrl(@RequestParam("fileName") String fileName, @RequestParam("bucketName") String bucketName) {String url = minioService.getPreviewUrl(fileName, bucketName);String previewUrl = null;try {if (url == null || StrUtil.isBlank(url)) {return Msg.SUCCESS.setNewMsg("不好意思,没查着该文件");}// 前端返回格式:ip:端口/桶名/文件名previewUrl = url.substring(0, url.indexOf("?"));} catch (Exception e) {log.error("预览文件地址错误,文件名为:{},bucket名为:{},错误信息为:", fileName, bucketName, e);}log.info("文件查找成功,文件预览地址为:{},文件名:{},bucket:{}", previewUrl, fileName, bucketName);return Msg.SUCCESS.setNewData(previewUrl);}/*** 下载文件** @param response* @param fileName   文件名* @param bucketName 桶名* @return*/@PostMapping("/download")public Msg download(HttpServletResponse response, @RequestParam("fileName") String fileName, @RequestParam("bucketName") String bucketName) {try {minioService.downloadFile(response, fileName, bucketName);log.info("文件下载成功,文件名称:{},bucket名为:{}", fileName, bucketName);return Msg.DOWNLOAD_SUCCESS;} catch (Exception e) {log.error("文件下载失败,文件名称:{},错误信息:", fileName, e);return Msg.DOWNLOAD_ERROR;}}/*** 删除文件** @param fileName   文件名* @param bucketName 桶名* @return*/@DeleteMapping("/delFile")public Msg delFile(@RequestParam("fileName") String fileName, @RequestParam("bucketName") String bucketName) {try {minioService.delFile(fileName, bucketName);log.info("文件删除成功,文件名称为:{},bucket为:{}", fileName, bucketName);return Msg.DELETE_SUCCESS.setNewData("删除文件:" + fileName + "成功!");} catch (Exception e) {log.error("删除文件失败,文件名称为:{},bucket为:{},错误信息:", bucketName, fileName, e);return Msg.DELETE_ERROR.setNewData("删除文件:" + fileName + "失败!");}}
}

pojo:

package com.greedy.minio.pojo;import lombok.Data;
import org.springframework.web.multipart.MultipartFile;import java.io.Serializable;/*** @Author: Greedy* @Date: Created in:2022-09-15* Description: 文件上传入参实体类*/
@Data
public class FileUploadBody implements Serializable {/*** 自定义文件名*/private String fileName;/*** 多文件*/private MultipartFile[] files;/*** 所属模块*/private String bucket;}

serviceImpl:

package com.greedy.minio.service.impl;import cn.hutool.core.util.StrUtil;
import com.greedy.minio.config.MinioConfig;
import com.greedy.minio.pojo.FileUploadBody;
import com.greedy.minio.service.MinioService;
import com.greedy.minio.vo.FileVo;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;/*** @Author: Greedy* @Date: Created in:2022-09-15* Description:*/
@Service
@Slf4j
public class MinioServiceImpl implements MinioService {@Autowiredprivate MinioConfig minioConfig;@Autowiredprivate MinioClient minioClient;/*** 上传文件* @param body* @return*/@Overridepublic List<FileVo> uploadFile(FileUploadBody body) {MultipartFile[] files=body.getFiles();if (Objects.nonNull(files) && files.length > 0) {String bucketName = StrUtil.isNotBlank(body.getBucket()) ? body.getBucket().replaceAll(",", "") : minioConfig.getBucketName();List<FileVo> resultList = new ArrayList<>();String fileName = null;for (MultipartFile file : files) {try {if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}fileName = file.getOriginalFilename();if (StrUtil.isNotBlank(body.getFileName())){fileName = body.getFileName();}StringBuffer fileNameSB = new StringBuffer();fileNameSB.append(System.currentTimeMillis()).append("_").append(bucketName).append("_");if (StrUtil.isNotBlank(fileName)){fileNameSB.append(fileName.replaceAll(",", ""));}fileName = fileNameSB.toString();PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();minioClient.putObject(args);FileVo fileVo=new FileVo();fileVo.setFileName(fileName);fileVo.setBucket(bucketName);fileVo.setPreviewUrl(getPreviewUrl(fileName,bucketName));resultList.add(fileVo);log.info("文件上传成功,文件名称:{},bucket名称:{}", fileName, bucketName);}catch (Exception e){log.error("文件上传失败,文件名称:{},bucket名称:{},错误信息:", fileName, bucketName, e);}}return resultList;}return Collections.emptyList();}/*** 获取预览地址* @param fileName* @param bucketName* @return*/@Overridepublic String getPreviewUrl(String fileName, String bucketName) {if (StrUtil.isNotBlank(fileName)) {bucketName = StrUtil.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();try {minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(fileName).build());if (null != minioConfig.getPreviewExpiry()){String presignedObjectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(fileName).expiry(minioConfig.getPreviewExpiry(), TimeUnit.HOURS).build());log.info("有时限文件预览地址为:{},文件名:{},bucket名:{},有效时间为:{}", presignedObjectUrl, fileName, bucketName, minioConfig.getPreviewExpiry());return presignedObjectUrl;}else {String presignedObjectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(fileName).build());log.info("文件预览地址为:{},文件名:{},bucket名:{},有效时间为:永久", presignedObjectUrl, fileName, bucketName);return presignedObjectUrl;}} catch (Exception e) {log.error("预览文件地址错误,文件名为:{},bucket名为:{},错误信息为:", fileName, bucketName, e);}}return null;}/*** 下载文件* @param response* @param fileName* @param bucketName*/@Overridepublic void downloadFile(HttpServletResponse response, String fileName, String bucketName) {InputStream inputStream = null;if (StrUtil.isNotBlank(fileName)) {bucketName = StrUtil.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();try {StatObjectResponse objectStat = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(fileName).build());response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));response.setContentType(objectStat.contentType());response.setCharacterEncoding("UTF-8");inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());IOUtils.copy(inputStream, response.getOutputStream());log.info("文件下载成功,文件名称:{},bucket名为:{}", fileName, bucketName);} catch (Exception e) {log.error("文件下载失败,文件名称:{},错误信息:", fileName, e);} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {log.error("输入流关闭失败,文件名:{},错误信息:", fileName, e);}}}}}/*** 删除文件* @param fileName* @param bucketName* @return*/@Overridepublic String delFile(String fileName, String bucketName) {if (StrUtil.isNotBlank(fileName)) {bucketName = StrUtil.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());log.info("文件删除成功,文件名称为:{},bucket为:{}", fileName, bucketName);return "success";}catch (Exception e) {log.error("删除文件失败,文件名称为:{},bucket为:{},错误信息:", bucketName, fileName, e);return "删除文件失败,请刷新后重试";}}return "文件不能为空";}
}

service:

package com.greedy.minio.service;import com.greedy.minio.pojo.FileUploadBody;
import com.greedy.minio.vo.FileVo;import javax.servlet.http.HttpServletResponse;
import java.util.List;/*** @Author: Greedy* @Date: Created in:2022/09/15* Description:*/
public interface MinioService {/*** 上传文件* @param body* @return*/List<FileVo> uploadFile(FileUploadBody body);/*** 获取预览地址* @param fileName* @param bucketName* @return*/String getPreviewUrl(String fileName, String bucketName);/*** 下载文件* @param response* @param fileName* @param bucketName*/void downloadFile(HttpServletResponse response, String fileName, String bucketName);/*** 删除文件* @param fileName* @param bucketName* @return*/String delFile(String fileName, String bucketName);
}

utils:这个统一结果返回实体类,在代码里换成你寄几的就行( •̀ ω •́ )✧

package com.greedy.minio.utils;import lombok.Data;/*** 统一返回结果集实体类* @param <T> 返回数据对象*/
@Data
public class Msg<T> {/*** 错误码*/private Integer Code;/*** 错误信息,一般为前端提示信息*/private String Msg;/*** 返回值,一般为成功后返回的数据*/private T data;/*** 错误详情,一般为失败后的详细原因,如空指针之类的*/private String Detail;public Msg() {}public Msg(Integer Code, String Msg) {this.Code = Code;this.Msg = Msg;}public Msg(Integer Code, String Msg, T data) {this.Code = Code;this.Msg = Msg;this.data = data;}/*** 配合静态对象直接设置 data 参数* @param data* @return*/public Msg setNewData(T data) {Msg error = new Msg();error.setCode(this.Code);error.setMsg(this.Msg);error.setDetail(this.Detail);error.setData(data);return error;}/*** 配合静态对象直接设置 errorMsg 参数* @param* @return*/public Msg setNewMsg(String Msg) {Msg error = new Msg();error.setCode(this.Code);error.setMsg(Msg);error.setDetail(this.Detail);error.setData(this.data);return error;}public static final Msg SUCCESS = new Msg(200, "成功");public static final Msg ERROR = new Msg(405, "失败");public static final Msg INSERT_SUCCESS = new Msg(200, "新增成功");public static final Msg UPDATE_SUCCESS = new Msg(200, "更新成功");public static final Msg DELETE_SUCCESS = new Msg(200, "删除成功");public static final Msg UPLOAD_SUCCESS = new Msg(200, "上传成功");public static final Msg DOWNLOAD_SUCCESS = new Msg(200, "下载成功");public static final Msg LOGIN_SUCCESS = new Msg(200, "登陆成功");public static final Msg LOGOUT_SUCCESS = new Msg(200, "登出成功");public static final Msg LOGIN_ERROR = new Msg(201, "登陆错误");public static final Msg LOGIN_EXPIRE = new Msg(202, "登陆过期");public static final Msg ACCESS_LIMITED = new Msg(301, "访问受限");public static final Msg ARGS_ERROR = new Msg(501, "参数错误");public static final Msg UNKOWN_ERROR = new Msg(502, "系统异常");public static final Msg INSERT_ERROR = new Msg(503, "新增错误");public static final Msg UPDATE_ERROR = new Msg(504, "更新错误");public static final Msg DELETE_ERROR = new Msg(506, "删除错误");public static final Msg UPLOAD_ERROR = new Msg(507, "上传错误");public static final Msg DOWNLOAD_ERROR = new Msg(508, "下载错误");public static final Msg OTHER_SYSTEM_ERROR = new Msg(509, "调用系统异常");//    return ErrorMsg.SUCCESS; 成功返回
//    return ErrorMsg.SUCCESS.setNewData(list); 成功带参返回
//    return ErrorMsg.LOGIN_ERROR.setNewErrorMsg("用户名或密码不正确"); 错误返回并设定自定义错误信息}

vo:

package com.greedy.minio.vo;import lombok.Data;import java.io.Serializable;/*** @Author: Greedy* @Date: Created in:2022-09-15* Description: 展示给前端的具体信息*/
@Data
public class FileVo implements Serializable {/*** 文件名称*/private String fileName;/*** 预览地址*/private String previewUrl;/*** 所属模块*/private String bucket;
}

MinioApp:主启动类省略。。。

application.yaml:

pom:

<dependencies><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>去mvn中央仓库自己找</version></dependency><!-- 工具类依赖 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.6</version></dependency><!-- 可以自行扩展,例如显示进度条等依赖 -->
</dependencies>

3、使用MinIO

代码Controller里面几个方法注释写的都很详细了,就不用说了吧。。。

如果您坚持到了这里了都,不给个赞可说不过去熬

minIO安装教程及代码使用相关推荐

  1. 联盛德W806入门教程-CDK安装教程及代码下烧录

    笔者使用的系统板如下图所示: 首先安装代码编译软件CDK: 硬件:⚫ W805/W806 开发板 ⚫ USB 转串口线 软件: Windows 端编译工具:CDK 安装包 链接:[https://pa ...

  2. minio安装教程 linux+windows

    下载文件 这个网站毛病,下载资源不能直接点,要在路由后端拼接地址才能访问,否则no found . 点击下面的链接直接下载对应系统的minio,不过可能需要科学上网工具,否则 下载速度比较慢,如果下载 ...

  3. 独家 | 手把手教你用Python 3创建用于机器学习开发的Linux虚拟机(附安装教程代码)

    原文标题:How to Create a Linux Virtual Machine For Machine Learning Development With Python 3 作者:Jason B ...

  4. 群晖NAS教程(十六)、利用Docker安装GitLab管理代码工具

    为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客 群晖NAS教程(十六).利用Docker安装GitLab管理代码工具 群晖DSM上安装GitLab有两种方式,一种是直接在群晖套件上安装,另一种是 ...

  5. Source Insight 3.5 Source Insight4.0 看代码神器 免费版 百度网盘下载,附详细安装教程。

    链接:https://pan.baidu.com/s/1IIALTQHovV9Zp0xetRfYYQ 密码:0mtk 一.Source Insight 3.5 安装教程: 1.下载文件中附有 Sour ...

  6. vs安装一直在提取文件_Visual Studio 2019下载及安装教程

    宸1分钟前 这可是我珍藏多年的资源啊. Visual Studio 2019 Microsoft Visual Studio(简称VS)是美国微软公司的开发工具包系列产品.是目前最流行的Windows ...

  7. 这套完美的Java环境安装教程,完整,详细,清晰可观,让你一目了然,简单易懂。⊙﹏⊙...

    JDK下载与安装教程 2017年06月18日 22:53:16 Danishlyy1995 阅读数:349980 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csd ...

  8. TensorFlow2.0 系列开篇: Windows下GPU版本详细安装教程

    点击上方"Datawhale",选择"星标"公众号 第一时间获取价值内容 [导读]今年三月谷歌在TensorFlow开发者峰会上宣布TensorFlow 2.0 ...

  9. Centos7上安装oracle11g/12c的安装教程推荐及注意事项

    Centos7上安装oracle11g的安装教程推荐及注意事项 历时一天半,终于在今天中午安装完oracle11g,成功后喜悦的心情自是溢于言表.总有些疑问,比如为何如此复杂的数据库为何还会有如此之多 ...

  10. Python2安装教程(以最终版本Python2.7.18为例)

    写在这里的初衷,一是备忘,二是希望得到高人指点,三是希望能遇到志同道合的朋友. 之前一直用的python3.6.5进行学习,最新试运行一些代码进行学习,发现是基于python2的环境下,就想着尝试着安 ...

最新文章

  1. 设计模式实例(Lua)笔记之五(Bridge模式)
  2. mac环境下myeclipse上配置tomcat
  3. Eclipse启动时报错
  4. Hive的列分隔符和行分隔符
  5. object.prototype.call
  6. MySQL学习笔记_4_MySQL创建数据表(下)
  7. X86Windows 相关链接....持续更新中....
  8. java.util.NoSuchElementException: None.get的解决方法
  9. 简单的docker下载安装jenkins
  10. c语言输入m行m列的二维数组,编写一个函数,用于计算具有n行和m列的二维数组中指定列的平均值以及数组各行的和的最小值。...
  11. 英雄传奇-6.专用浏览器打不开.黑屏.白屏.插件丢失等怎么解决
  12. 小米无线网卡linux,NanoPi NEO安装小米随身WiFi
  13. 用图片替代cursor光标样式
  14. OBS+SRS+centos7搭建局域网直播推流服务器
  15. iOS动画——流光文字
  16. java gc 命令_Java 查看系统GC命令介绍
  17. 指南:清晰理解zkEVM、EVM 兼容性和Rollup
  18. 视频特征提取常用范式总结
  19. HTML哪个单位是角度,css 角度单位有哪些?
  20. 前端开发实习面试题(JavaScript篇)

热门文章

  1. synchdem matlab,数字高程模型(DEM)移动插值算法
  2. 小样本算法库LibFewShot
  3. win7(64位)+vs2010+orge1.8.1
  4. html古风颜色代码,数字报纸HTML版本
  5. vuex中subscribe的使用
  6. CSS / 清除浮动+切图+属性书写顺序+页面布局思路
  7. 2016网易春季校园招聘产品策划笔试
  8. 用html语言设计李白的一首诗,李白《赠汪伦》的教案设计
  9. mac os x excel 单元格换行
  10. 安装服务器系统后鼠标键盘没反应,安装Win7系统以后键盘鼠标不能用/失灵没反应的缘由以及解决方法...