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,一经查实,立即删除!

相关文章

python - 分割 pytest 的 conftest.py 文件

解决 pytest 的 conftest.py 文件过大问题。 1. 项目目录结构 project_name ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── project_name │ ├── __init__.py │ ├── testing │ │ ├── __init__.py │ │ ├── fixtur…

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;提高网站在搜索引擎中的自然排名&…

python爱心树表白代码

以下是一个使用Python的turtle模块来绘制一颗爱心并表白的简单示例代码&#xff1a; import turtle import math # 设置屏幕 screen turtle.Screen() screen.bgcolor("black") # 绘制爱心 def draw_heart(t, size): t.speed(9) t.penup() t.goto(0, -size…

Python Minio 工具类封装

最近因为需要对大规模的文件进行存储&#xff0c;选了多种对象存储方案&#xff0c;最终选择了MinIO&#xff0c;为了方便python的调用&#xff0c;在minio第三方包的基础上进行进一步封装调用&#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;我们需要明确小程序的核心功能和特色。包括设定活动类型、返利…

Python学习(3) 函数

定义 定义一个函数的格式&#xff1a; def 函数名(参数):执行代码如果没有参数&#xff0c;则称为无参函数。 定义时小括号中写的是形参&#xff08;形式参数&#xff09;&#xff0c;调用时写的是实参&#xff08;实际参数&#xff09;。 调用 调用格式&#xff1a; def…

【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. 传递文…

怎么通过OpenAI API调用其多模态大模型(GPT-4o)

现在只要有额度&#xff0c;大家都可以调用OpenAI的多模态大模型了&#xff0c;例如GPT-4o和GPT-4 Turbo&#xff0c;我一年多前总结过一些OpenAI API的用法&#xff0c;发现现在稍微更新了一下。主要参考了这里&#xff1a;https://platform.openai.com/docs/guides/vision 其…

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

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

k8s——Pod详解

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

缪尔赛思又来到了你的面前(哈希)

定义一棵根节点为 1 1 1&#xff0c; n ( 2 ≤ n ≤ 1 0 3 ) n(2≤n≤10^3) n(2≤n≤103) 个节点的树的哈希值为&#xff1a; H ∑ i 1 n X i Y f a ( i ) m o d 998244353 H∑^n_{i1}X^iY^{fa(i)}\ mod\ 998244353 Hi1∑n​XiYfa(i) mod 998244353 f a ( i ) fa(i) fa(i)…

断网之后的页面,Autox.js是点击还是上下滑动比较好?

在处理断网之后的页面&#xff0c;选择点击还是上下滑动作为刷新操作&#xff0c;取决于应用的设计和用户界面。通常&#xff0c;这两种操作都可以作为刷新页面的方式&#xff0c;但它们各自有不同的适用场景&#xff1a; 点击刷新 - 适用场景&#xff1a;如果应用提供了一个明…

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

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

C#串口通信-串口相关参数介绍

串口通讯(Serial Communication)&#xff0c;是指外设和计算机间&#xff0c;通过数据信号线、地线等&#xff0c;按位进行传输数据的一种双向通讯方式。 串口是一种接口标准&#xff0c;它规定了接口的电气标准&#xff0c;没有规定接口插件电缆以及使用的通信协议&#xff0c…