Springboot整合Minio对象存储超级详细讲解以及配置搭建

windows环境下搭建minio步骤

1.从minio官网进行查看详细信息

	地址:https://min.io/里面有详细的配置信息搭建成功之后如下如所示:用户名密码默认情况下为 username:minioadmin password:minioadmin

在这里插入图片描述

2.搭建成功之后的访问

	地址:服务ip 端口9000http//127.0.0.1:9000 用户名密码为默认:minioadmin 创建桶时候要注意桶的名称

在这里插入图片描述

springboot整合和minio的步骤如下

1.pom坐标的指定

<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.2.2</version></dependency><!-- Hutool --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.18</version></dependency>

2.配置文件的设置如下

package com.java.javamethod.conf;import io.minio.MinioClient;
import lombok.SneakyThrows;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;/*** Minio配置类* @Author ww* @Date 2024/5/21 10:06* @Version 1.0*/@Configuration
@EnableConfigurationProperties(MinioProperties.class)
@ConditionalOnProperty(value = "oss.name", havingValue = "minio")
public class MinioConfiguration {@Resourceprivate MinioProperties ossProperties;@Bean@SneakyThrowspublic MinioClient minioClient() {return MinioClient.builder().endpoint(ossProperties.getEndpoint()).credentials(ossProperties.getAccessKey(), ossProperties.getSecretKey()).build();}}
package com.java.javamethod.conf;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;/*** @Author ww* @Date 2024/5/21 10:08* @Version 1.0*/
@Data
@ConfigurationProperties(prefix = MinioProperties.PREFIX)
public class MinioProperties {/*** 配置前缀*/public static final String PREFIX = "oss";/*** 对象存储名称*/private String name;/*** 对象存储服务的URL*/private String endpoint;/*** Access key 账户ID*/private String accessKey;/*** Secret key 密码*/private String secretKey;/*** 默认的存储桶名称*/private String bucketName = "qditwei";/*** 可上传的文件后缀名*/private List<String> fileExt;}

3.minio工具类的封装

package com.java.javamethod.service;import com.java.javamethod.domain.OssFile;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.List;/*** @Author ww* @Date 2024/5/21 10:54* @Version 1.0*/
public interface OssTemplate {/*** 存储桶是否存在** @param bucketName 存储桶名称* @return boolean*/boolean bucketExists(String bucketName);/*** 获取文件信息** @param fileName 存储桶文件名称* @return InputStream*/OssFile getOssInfo(String fileName);/*** 上传文件** @param folderName 上传的文件夹名称* @param fileName   上传文件名* @param file       上传文件类* @return BladeFile*/OssFile upLoadFile(String folderName, String fileName, MultipartFile file);/*** 上传文件** @param folderName 上传的文件夹名称* @param fileName   存储桶对象名称* @param suffix     文件后缀名* @param stream     文件流* @return BladeFile*/OssFile upLoadFile(String folderName, String fileName, String suffix, InputStream stream);/*** 删除文件** @param fileName 存储桶对象名称*/boolean removeFile(String fileName);/*** 批量删除文件** @param fileNames 存储桶对象名称集合*/boolean removeFiles(List<String> fileNames);/*** @Description: 下载文件* @Param response: 响应* @Param fileName: 文件名* @Param filePath: 文件路径* @return: void*/void downloadFile(HttpServletResponse response, String fileName, String filePath);
}package com.java.javamethod.util;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ObjectUtil;
import com.java.javamethod.conf.MinioProperties;
import com.java.javamethod.domain.OssFile;
import com.java.javamethod.service.OssTemplate;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.DeleteObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.stream.Stream;/*** @Author ww* @Date 2024/5/21 10:52* @Version 1.0*/@Slf4j
@Service
public class MinioTemplate implements OssTemplate {/*** MinIO客户端*/@Resourceprivate MinioClient client;/*** 配置类*/@Resourceprivate MinioProperties ossProperties;/*** 格式化时间*/private static final String DATE_FORMAT = "yyyyMMdd";/*** 字符集*/private static final String ENCODING = "UTF-8";/*** 存储桶是否存在** @param bucketName 存储桶名称* @return boolean*/@Overridepublic boolean bucketExists(String bucketName) {try {return client.bucketExists(BucketExistsArgs.builder().bucket(getBucketName(bucketName)).build());} catch (Exception e) {log.error("minio bucketExists Exception:{}", e);}return false;}/*** @Description: 创建 存储桶* @Param bucketName: 存储桶名称*/public void makeBucket(String bucketName) {try {if (!client.bucketExists(BucketExistsArgs.builder().bucket(getBucketName(bucketName)).build())) {client.makeBucket(MakeBucketArgs.builder().bucket(getBucketName(bucketName)).build());log.info("minio makeBucket success bucketName:{}", bucketName);}} catch (Exception e) {log.error("minio makeBucket Exception:{}", e);}}/*** 获取文件信息** @param fileName 存储桶文件名称* @return InputStream*/@Overridepublic OssFile getOssInfo(String fileName) {try {StatObjectResponse stat = client.statObject(StatObjectArgs.builder().bucket(getBucketName(ossProperties.getBucketName())).object(fileName).build());OssFile ossFile = new OssFile();ossFile.setName(ObjectUtil.isEmpty(stat.object()) ? fileName : stat.object());ossFile.setFilePath(ossFile.getName());ossFile.setDomain(getOssHost(ossProperties.getBucketName()));ossFile.setHash(String.valueOf(stat.hashCode()));ossFile.setSize(stat.size());ossFile.setPutTime(DateUtil.date(stat.lastModified().toLocalDateTime()));ossFile.setContentType(stat.contentType());return ossFile;} catch (Exception e) {log.error("minio getOssInfo Exception:{}", e);}return null;}/*** 上传文件** @param folderName 上传的文件夹名称* @param fileName   上传文件名* @param file       上传文件类* @return BladeFile*/@Override@SneakyThrowspublic OssFile upLoadFile(String folderName, String fileName, MultipartFile file) throws RuntimeException {if (file == null || file.isEmpty()) {throw new RuntimeException("文件不能为空");}// 文件大小if (file.getSize() > 5 * 1024 * 1024) {throw new RuntimeException("文件大小不能超过5M");}String suffix = getFileExtension(file.getOriginalFilename());// 文件后缀判断/*if (!CollUtil.contains(ossProperties.getFileExt(), suffix)) {String error = String.format("文件类型错误,目前支持[%s]等文件类型",String.join(",", ossProperties.getFileExt()));throw new RuntimeException(error);}*/try {return upLoadFile(folderName, fileName, suffix, file.getInputStream());} catch (Exception e) {log.error("minio upLoadFile Exception:{}", e);throw new RuntimeException("文件上传失败,请重新上传或联系管理员");}}/*** 获取文件后缀名** @param fullName 文件全名* @return {String}*/public static String getFileExtension(String fullName) {Assert.notNull(fullName, "minio file fullName is null.");String fileName = new File(fullName).getName();int dotIndex = fileName.lastIndexOf('.');return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);}/*** 上传文件** @param folderName 上传的文件夹名称* @param fileName   存储桶对象名称* @param suffix     文件后缀名* @param stream     文件流* @return BladeFile*/@Overridepublic OssFile upLoadFile(String folderName, String fileName, String suffix, InputStream stream) {try {return upLoadFile(ossProperties.getBucketName(), folderName, fileName, suffix, stream,"application/octet" + "-stream");} catch (Exception e) {log.error("minio upLoadFile Exception:{}", e);}return null;}/*** @Description: 上传文件* @Param bucketName: 存储桶名称* @Param folderName: 上传的文件夹名称* @Param fileName: 上传文件名* @Param suffix: 文件后缀名* @Param stream: 文件流* @Param contentType: 文件类型*/@SneakyThrowspublic OssFile upLoadFile(String bucketName, String folderName, String fileName, String suffix, InputStream stream,String contentType) {if (!bucketExists(bucketName)) {log.info("minio bucketName is not creat");makeBucket(bucketName);}OssFile file = new OssFile();String originalName = fileName;String filePath = getFilePath(folderName, fileName, suffix);client.putObject(PutObjectArgs.builder().bucket(getBucketName(bucketName)).object(filePath).stream(stream, stream.available(), -1).contentType(contentType).build());file.setOriginalName(originalName);file.setName(filePath);file.setDomain(getOssHost(bucketName));file.setFilePath(filePath);stream.close();log.info("minio upLoadFile success, filePath:{}", filePath);return file;}/*** 删除文件** @param fileName 存储桶对象名称*/@Overridepublic boolean removeFile(String fileName) {try {client.removeObject(RemoveObjectArgs.builder().bucket(getBucketName(ossProperties.getBucketName())).object(fileName).build());log.info("minio removeFile success, fileName:{}", fileName);return true;} catch (Exception e) {log.error("minio removeFile fail, fileName:{}, Exception:{}", fileName, e);}return false;}/*** 批量删除文件** @param fileNames 存储桶对象名称集合*/@Overridepublic boolean removeFiles(List<String> fileNames) {try {Stream<DeleteObject> stream = fileNames.stream().map(DeleteObject::new);client.removeObjects(RemoveObjectsArgs.builder().bucket(getBucketName(ossProperties.getBucketName())).objects(stream::iterator).build());log.info("minio removeFiles success, fileNames:{}", fileNames);return true;} catch (Exception e) {log.error("minio removeFiles fail, fileNames:{}, Exception:{}", fileNames, e);}return false;}/*** @Description: 下载文件* @Param response: 响应* @Param fileName: 文件名* @Param filePath: 文件路径*/@Overridepublic void downloadFile(HttpServletResponse response, String fileName, String filePath) {GetObjectResponse is = null;try {GetObjectArgs getObjectArgs =GetObjectArgs.builder().bucket(ossProperties.getBucketName()).object(filePath).build();is = client.getObject(getObjectArgs);// 设置文件ContentType类型,这样设置,会自动判断下载文件类型response.setContentType("application/x-msdownload");response.setCharacterEncoding(ENCODING);// 设置文件头:最后一个参数是设置下载的文件名并编码为UTF-8response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, ENCODING));IoUtil.copy(is, response.getOutputStream());log.info("minio downloadFile success, filePath:{}", filePath);} catch (Exception e) {log.error("minio downloadFile Exception:{}", e);} finally {IoUtil.close(is);}}/*** 获取文件外链** @param bucketName bucket名称* @param fileName   文件名称* @param expires    过期时间* @return url*/public String getPresignedObjectUrl(String bucketName, String fileName, Integer expires) {String link = "";try {link = client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(getBucketName(bucketName)).object(fileName).expiry(expires).build());} catch (Exception e) {log.error("minio getPresignedObjectUrl is fail, fileName:{}", fileName);}return link;}/*** 根据规则生成存储桶名称规则** @param bucketName 存储桶名称* @return String*/private String getBucketName(String bucketName) {return bucketName;}/*** 根据规则生成文件路径** @param folderName       上传的文件夹名称* @param originalFilename 原始文件名* @param suffix           文件后缀名* @return string 上传的文件夹名称/yyyyMMdd/原始文件名_时间戳.文件后缀名*/private String getFilePath(String folderName, String originalFilename, String suffix) {return StrPool.SLASH + String.join(StrPool.SLASH, folderName, DateUtil.date().toString(DATE_FORMAT),originalFilename) + StrPool.C_UNDERLINE + DateUtil.current() + StrPool.DOT + suffix;}/*** 获取域名** @param bucketName 存储桶名称* @return String*/public String getOssHost(String bucketName) {return ossProperties.getEndpoint() + StrPool.SLASH + getBucketName(bucketName);}}

4.swagger功能的验证

package com.java.javamethod.controller;import com.java.javamethod.domain.OssFile;
import com.java.javamethod.util.MinioTemplate;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;/*** @Author ww* @Date 2024/5/21 10:23* @Version 1.0*/
@RestController
@Api(tags = "文件控制器", description = "文件管理控制器")
public class FileController {@ResourceMinioTemplate minioTemplate;@PostMapping("/upload")@ApiImplicitParams(value = {@ApiImplicitParam(name = "folderName", value = "文件路径", required = true, dataType = "String"),@ApiImplicitParam(name = "fileName", value = "文件名", required = true, dataType = "String")})   // 注意seagger上传文件时候一定要加@RequestPart否则可能没法进行上传文件public OssFile upload(String folderName, String fileName,@RequestPart MultipartFile file) {return minioTemplate.upLoadFile( folderName, fileName, file);}}

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/15095.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue项目实战 - 如果高效的实现防抖和节流

在Vue项目中&#xff0c;处理高频事件的优化至关重要&#xff0c;直接影响用户体验和应用性能。防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;是两种常用且有效的方法&#xff0c;可以控制事件触发频率&#xff0c;减少不必要的资源消耗。如何在…

SEO优化,小白程序员如何做SEO优化流量从0到1

原文链接&#xff1a;SEO优化&#xff0c;小白程序员如何做SEO优化流量从0到1 1、SEO是什么&#xff1f; SEO即&#xff1a;搜索引擎优化(Search Engine Optimization)&#xff0c;是一种通过优化网站结构、内容和外部链接等因素&#xff0c;提高网站在搜索引擎中的自然排名&…

DeepDriving | CUDA编程-03:线程层级

本文来源公众号“DeepDriving”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;CUDA编程-03:线程层级 DeepDriving | CUDA编程-01&#xff1a; 搭建CUDA编程环境-CSDN博客 DeepDriving | CUDA编程-02&#xff1a; 初识CUDA编程-C…

Linux之共享内存mmap用法实例(六十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

外卖霸王餐返利外卖会员卡小程序开发

外卖霸王餐返利外卖会员卡小程序开发 "社交电商赋能下的外卖返利小程序"是专为商家与用户双赢而设计的创新平台。 以下是其开发方案的详细步骤&#xff1a; 一、需求梳理&#xff1a;首先&#xff0c;我们需要明确小程序的核心功能和特色。包括设定活动类型、返利…

【Docker】Linux 系统(CentOS 7)安装 Docker

文章目录 对 VMware 软件的建议官方说明文档Docker安装卸载旧版本docker设置仓库开始安装 docker 引擎最新版 Docker 安装指定版本 Docker 安装&#xff08;特殊需求使用&#xff09; 启动 Docker查看 Docker 版本查看 Docker 镜像设置 Docker 开机自启动 验证开机启动是否生效…

自定义原生小程序顶部及获取胶囊信息

需求&#xff1a;我需要将某个文字或者按钮放置在小程序顶部位置 思路&#xff1a;根据获取到的顶部信息来定义我需要放的这个元素样式 * 这里我是定义某个指定页面 json&#xff1a;给指定页面的json中添加自定义设置 "navigationStyle": "custom" JS&am…

新时代AI浪潮下,程序员和产品经理如何入局AIGC领域?

当下&#xff0c;AI浪潮席卷全球&#xff0c;AIGC大模型技术已经成为当今技术领域的一个重要趋势&#xff0c;对于产品经理来说&#xff0c;掌握这项技术不仅能够增强他们的职业技能&#xff0c;还能在竞争激烈的职场中脱颖而出。 为什么呢&#xff1f; 把握AI时代的机遇 AI技…

StringMVC

目录 一&#xff0c;MVC定义 二&#xff0c;SpringMVC的基本使用 2.1建立连接 - RequestMapping("/...") ​编辑 2.2请求 1.传递单个参数 2.传递多个参数 3.传递对象 4.参数重命名 5.传递数组 6. 传递集合 7.传递JSON数据 8. 获取url中数据 9. 传递文…

python数据类型之元组、集合和字典

目录 0.三者主要作用 1.元组 元组特点 创建元组 元组解包 可变和不可变元素元组 2.集合 集合特点 创建集合 集合元素要求 集合方法 访问与修改 子集和超集 相等性判断 集合运算 不可变集合 3.字典 字典特点 字典创建和常见操作 字典内置方法 pprin模块 0.…

k8s——Pod详解

一、Pod基础概念 1.1 Pod定义 Pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&#xff0c;用于管理Pod运行…

Java进阶学习笔记7——权限修饰符

什么是权限修饰符&#xff1f; 就是用来限制类中的成员&#xff08;成员变量、成员方法、构造器、代码块....&#xff09;能够被访问的范围。 protected使用的比较少&#xff0c;但是程序员还是要阅读代码&#xff0c;看官方文档是怎么写的&#xff0c;都会接触到protected修饰…

性能测试场景的设计方法

引用&#xff1a;根据2008年Aberdeen Group的研究报告&#xff0c;对于Web网站&#xff0c;1秒的页面加载延迟相当于少了11%的PV&#xff08;page view&#xff09;&#xff0c;相当于降低了16%的顾客满意度。如果从金钱的角度计算&#xff0c;就意味着&#xff1a;如果一个网站…

「探讨」:什么是网络审计?好用的网络审计系统推荐【图文详解】

网络是企业运营、政府管理、个人生活不可或缺的基础设施。 然而网络安全问题却日益凸显&#xff0c;数据泄露、网络攻击、欺诈行为等风险日益严重。 一、网络审计的定义 网络审计&#xff0c;又称信息技术审计或电子审计&#xff0c;是指审计人员运用专业技能和工具&#xff…

实战之快速完成 ChatGLM3-6B 在 GPU-8G的 INT4 量化和本地部署

ChatGLM3 (ChatGLM3-6B) 项目地址 https://github.com/THUDM/ChatGLM3大模型是很吃CPU和显卡的&#xff0c;所以&#xff0c;要不有一个好的CPU&#xff0c;要不有一块好的显卡&#xff0c;显卡尽量13G&#xff0c;内存基本要32GB。 清华大模型分为三种(ChatGLM3-6B-Base&…

“大数据建模、分析、挖掘技术应用研修班”的通知!

随着2015年9月国务院发布了《关于印发促进大数据发展行动纲要的通知》&#xff0c;各类型数据呈现出了指数级增长&#xff0c;数据成了每个组织的命脉。今天所产生的数据比过去几年所产生的数据大好几个数量级&#xff0c;企业有了能够轻松访问和分析数据以提高性能的新机会&am…

Vue3中为Ant Design Vue中table的checkbox加tooltip、popover

问题的产生 Vue版本&#xff1a;3.3.13 ant-design-vue 版本&#xff1a;3.x.x 在工作时遇到一个场景&#xff0c;需要在 ant-table 的 checkbox 被禁用的时候提示原因&#xff0c;但是在 ant-design-vue 文档中并没有发现有相关介绍。 首先我去看了issue中是否有提到相关问题…

【金砖赛】基于docker搭链

一&#xff0e;基于docker搭建 启动并检查是否启动成功 #启动命令 sudo systemctl start docker#检查命令 sudo systemctl status docker修改权限 chomd 777 build_chain.sh 进行4节点联盟链搭建&#xff08;举例&#xff09; sudo ./build_chain.sh -d -l "127.0.0.1…

基于Android Studio记事本系统

目录 项目介绍 图片展示 运行环境 获取方式 项目介绍 具有登录&#xff0c;注册&#xff0c;记住密码&#xff0c;自动登录的功能&#xff1b; 可以新增记事本&#xff0c;编辑&#xff0c;删除记事本信息&#xff0c;同时可以设置主标题&#xff0c;内容&#xff0c;以及…

Ansible自动化运维中的Setup收集模块应用详解

作者主页&#xff1a;点击&#xff01; Ansible专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年5月22日13点14分 &#x1f4af;趣站推荐&#x1f4af; 前些天发现了一个巨牛的&#x1f916;人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xf…