当前位置: 首页 > news >正文

Minio入门系列【7】Spring Boot集成Minio

1 前言

之前介绍了如何使用Minio提供的JAVA SDK进行上传和下载文件,在此基础上,我们可以使用spring boot集成Minio JAVA SDK,添加自动配置、装配、客户端管理等功能,简化开发

2 Spring Boot集成Minio

2.1 环境搭建

首先我们搭建一个spring boot基础工程,引入以下依赖

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- https://mvnrepository.com/artifact/io.minio/minio --><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.3.1</version></dependency><dependency><groupId>me.tongfei</groupId><artifactId>progressbar</artifactId><version>0.9.2</version></dependency><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.2</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.13</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency><!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency>

2.2 操作模板类

在spring中,提供了很多集成第三方的操作模板类,比如RedisTemplate、RestTemplate等等,我们可以参照这些,提供一个minio SDK的集成模板类,这样在使用API时就比较方便了。

首先需要创建一个OSS文件对象,上传文件成功后,我们需要将文件信息返回给前端

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;/*** @author wuKeFan* @date 2020/9/10*/
@RefreshScope
@Configuration
public class OssConfig {@Value("${biz.oss.endpoint}")private String endpoint;@Value("${biz.oss.bucket}")private String bucket;@Value("${biz.oss.access-key-id}")private String accessKeyId;@Value("${biz.oss.access-key-secret}")private String accessKeySecret;@Value("${biz.oss.type}")private Integer ossType;/*** 最大上传长度单位m,默认20M*/@Value("${biz.oss.maxLength:20}")private Integer maxLength;public String getAccessId() {return accessKeyId;}public String getBucket() {return bucket;}public String getEndpoint() {return endpoint;}public Integer getMaxLength() {return maxLength;}public void setEndpoint(String endpoint) {this.endpoint = endpoint;}public void setBucket(String bucket) {this.bucket = bucket;}public String getAccessKeyId() {return accessKeyId;}public void setAccessKeyId(String accessKeyId) {this.accessKeyId = accessKeyId;}public String getAccessKeySecret() {return accessKeySecret;}public void setAccessKeySecret(String accessKeySecret) {this.accessKeySecret = accessKeySecret;}public void setMaxLength(Integer maxLength) {this.maxLength = maxLength;}public Integer getOssType() {return ossType;}public void setOssType(Integer ossType) {this.ossType = ossType;}
}
import com.mall4j.cloud.common.exception.Mall4cloudException;
import com.mall4j.cloud.common.response.ResponseEnum;
import io.minio.*;
import io.minio.http.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.concurrent.TimeUnit;/*** @author wuKeFan*/
@Component
public class MinioTemplate implements InitializingBean {@Autowiredprivate OssConfig ossConfig;private MinioClient minioClient;static  final Logger logger = LoggerFactory.getLogger(MinioTemplate.class);@Overridepublic void afterPropertiesSet() {this.minioClient =  MinioClient.builder().endpoint(ossConfig.getEndpoint()).credentials(ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret()).build();}/*** 删除文件** @param objectName 文件名称* @throws Exception 参考https://docs.minio.io/cn/java-client-api-reference.html#removeObject*/public void removeObject(String objectName) throws Exception {minioClient.removeObject(RemoveObjectArgs.builder().object(objectName).bucket(ossConfig.getBucket()).build());}/*** 获得上传的URL* @param objectName 文件路径(对象名)*/public String getPresignedObjectUrl(String objectName){try {return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(ossConfig.getBucket()).object(objectName).expiry(10, TimeUnit.MINUTES).method(Method.PUT).build());} catch (Exception e) {e.printStackTrace();throw new Mall4cloudException(ResponseEnum.EXCEPTION);}}public void uploadMinio(byte[] bytes, String filePath, String contentType) throws IOException {InputStream input = null;try {input = new ByteArrayInputStream(bytes);minioClient.putObject(PutObjectArgs.builder().bucket(ossConfig.getBucket()).contentType(contentType).stream(input, input.available(), -1).object(filePath).build());} catch (Exception e) {logger.error("minio上传文件错误:", e);} finally {if (Objects.nonNull(input)) {input.close();}}}
}

2.3 自动配置

在了解了BAT公司提供的对象存储OSS后,发现其API接口标准都是差不多的,从扩展性的角度出发,我们当前服务应当支持各种类型的OSS,比如阿里等。所以这里先定义一个枚举类,提供除了Minio还适配其他厂商的支持。

/*** 文件上传存储类型* @author wuKeFan* @date 2021/01/20*/
public enum OssType {/*** 阿里云oss*/ALI(0),/*** minio*/MINIO(1),
;private final Integer value;public Integer value() {return value;}OssType(Integer value) {this.value = value;}}

3 测试

首先,在yml中添加Minio的配置:

biz:oss:# resources-url是带有bucket的resources-url: http://127.0.0.1:9000/mall4cloud# 文件上传类型 0.阿里云 1.miniotype: 1endpoint: http://127.0.0.1:9000bucket: mall4cloudaccess-key-id: usernameaccess-key-secret: password

然后创建一个访问接口,直接调用minioTemplate进行文件操作,这样就十分便利,达到了简化开发的目的

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.mall4j.cloud.biz.config.MinioTemplate;
import com.mall4j.cloud.biz.config.OssConfig;
import com.mall4j.cloud.biz.constant.OssType;
import com.mall4j.cloud.biz.vo.OssVO;
import com.mall4j.cloud.common.response.ServerResponseEntity;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;/*** @author wuKeFan* @date 2020/9/10*/
@RequestMapping(value = "/oss")
@RestController
@Tag(name = "文件管理")
public class OssController {/*** 上传的文件夹(根据时间确定)*/public static final String NORM_DAY_PATTERN = "yyyy/MM/dd";@Autowiredprivate OssConfig ossConfig;@Autowiredprivate MinioTemplate minioTemplate;@GetMapping(value = "/info")@Operation(summary = "token" , description = "获取文件上传需要的token")@Parameter(name = "fileNum", description = "需要获取token的文件数量")public ServerResponseEntity<OssVO> info(@RequestParam("fileNum") Integer fileNum) {OssVO ossVO = new OssVO();// minio文件上传if (Objects.equals(ossConfig.getOssType(), OssType.MINIO.value())) {fillMinIoInfo(ossVO, fileNum);}return ServerResponseEntity.success(ossVO);}private void fillMinIoInfo(OssVO ossVo, Integer fileNum) {List<OssVO> ossVOList = new ArrayList<>();for (int i = 0; i<fileNum; i++) {OssVO oss = loadOssVO(new OssVO());String actionUrl = minioTemplate.getPresignedObjectUrl(oss.getDir() + oss.getFileName());oss.setActionUrl(actionUrl);ossVOList.add(oss);}ossVo.setOssList(ossVOList);}private OssVO loadOssVO(OssVO ossVo) {String dir = DateUtil.format(new Date(), NORM_DAY_PATTERN)+ "/";String fileName = IdUtil.simpleUUID();ossVo.setDir(dir);ossVo.setFileName(fileName);return ossVo;}@PostMapping("/upload_minio")@Operation(summary = "文件上传接口" , description = "上传文件,返回文件路径与域名")public ServerResponseEntity<OssVO> uploadFile(@RequestParam("file") MultipartFile file) throws IOException {if (file.isEmpty()) {return ServerResponseEntity.success();}OssVO oss = loadOssVO(new OssVO());minioTemplate.uploadMinio(file.getBytes(), oss.getDir() + oss.getFileName(), file.getContentType());return ServerResponseEntity.success(oss);}}

相关文章:

Minio入门系列【7】Spring Boot集成Minio

1 前言 之前介绍了如何使用Minio提供的JAVA SDK进行上传和下载文件&#xff0c;在此基础上&#xff0c;我们可以使用spring boot集成Minio JAVA SDK&#xff0c;添加自动配置、装配、客户端管理等功能&#xff0c;简化开发 2 Spring Boot集成Minio 2.1 环境搭建 首先我们搭…...

抖音视频下载.py(23年9月份可用)

声明:仅供学习交流使用!!! 抖音无水印视频下载; 首先登录抖音网页端 打开要下载的视频userId 然后编码实现下载 最后是完整代码,拿走就能用那种: # _*_ coding:utf-8 _*_import json import requests import time import randomheaders = """Accept: a…...

项目基本搭建流程

项目创立&#xff1a;webapp 设置maven 的和settings.xml 的地址 手动建立java文件夹和resource文件夹 一.分层 二.使用generator 来自动建立实体类dao 和dao接口,存放sql文件的xml&#xff1b;并复制到项目中&#xff08;路径可能可以直接设置&#xff09; 三. 配置文件&…...

学习pytorch11 神经网络-非线性激活

神经网络-非线性激活 官网文档常用1 ReLUinplace 常用2 Sigmoid 代码logs B站小土堆学习pytorch视频 非常棒的up主&#xff0c;讲的很详细明白 官网文档 https://pytorch.org/docs/stable/nn.html#non-linear-activations-weighted-sum-nonlinearity 常用1 ReLU 对输入做截断…...

Jenkins学习笔记2

Jenkins下载安装&#xff1a; 从清华源开源镜像站上下载jenkins的安装包&#xff1a; 安装的是这个版本。 关于软件的版本&#xff0c;尽量使用LTS&#xff0c;长期支持。 首先是安装openjdk&#xff1a; yum install fontconfig java-11-openjdk[rootlocalhost soft]# java …...

自动化测试:yaml结合ddt实现数据驱动!

在pythonunittestseleniumddt的框架中&#xff0c;数据驱动常见有以下几种方式实现&#xff1a; Csv/txtExcelYAML 本文主要给大家介绍测试数据存储在YAML文件中的使用场景。首先先来简单介绍一下YAML。 1. 什么是YAML 一种标记语言类似YAML&#xff0c;它实质上是一种通用…...

高效管理,轻松追踪——Chrono Plus for Mac任务管理工具

Chrono Plus for Mac是一款专注于任务管理和跟踪的应用程序。它提供了一种直观、清晰的界面&#xff0c;使您能够轻松创建、安排和分类任务。无论是个人项目还是团队合作&#xff0c;Chrono Plus都能为您提供一种有效组织和管理任务的方式。 这个应用程序具有多种强大的功能&a…...

python项目2to3方案预研

目录 官方工具2to3工具安装参数解释基本使用工具缺陷 future工具安装参数解释基本使用工具缺陷 python-modernize工具安装参数解释基本使用工具缺陷 pyupgrade工具安装参数解释基本使用工具缺陷 对比 官方工具2to3 2to3 是Python官方提供的用于将Python 2代码转换为Python 3代…...

MongoDB 是什么和使用场景概述(技术选型)

一、从NOSQL(Not Only SQL)说起 常见的数据库可以分为下面的两种类型&#xff1a; RDBMS&#xff08;关系型数据库&#xff09;&#xff1a;常见的关系型数据库有 Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL&#xff1b;NoSQL&#xff08;非关系型数据库&a…...

打印 pyspark.sql.dataframe.DataFrame 有哪些列

在 PySpark 中&#xff0c;要打印 pyspark.sql.dataframe.DataFrame 的列&#xff0c;可以使用 columns 属性。以下是一个示例代码&#xff1a; from pyspark.sql import SparkSession# 创建 SparkSession spark SparkSession.builder.getOrCreate()# 假设您的 DataFrame 名称…...

什么是虚拟DOM(Virtual DOM)?它在前端框架中的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是虚拟DOM&#xff08;Virtual DOM&#xff09;&#xff1f;⭐ 虚拟DOM 在前端框架中的作用⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&…...

QT实现简易时钟

头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> #include <QDebug> #include <QPainter> #include <QTimerEvent> #include <QTimer> #include <QTime>QT_BEGIN_NAMESPACE namespace Ui { cl…...

win禁用更新,取消windows更新提示,禁用windows自动更新

取消windows自动更新 前言&#xff1a;跟着我的节奏一步一步点下去&#xff0c;就OK 第一步第二步第三步第四步第五步第六步第七步 新建文件第八步 新增文件名称&#xff1a;FlightSettingsMaxPauseDays第九步 设置暂停更新天数第十步 选中你设置的最大值 前言&#xff1a;跟着…...

倒计时列表实现(小程序端Vue)

//rich-text主要用来将展示html格式的&#xff0c;可以直接使用这个标签 <view class"ptBox" v-for"(item,index) in orderList" :key"index"> <rich-text :nodes"item.limit_time|limitTimeFilter"></rich-text>…...

ContentType:application/x-www-form-urlencoded请求方法遇到的坑【PHP】

有些API要求请求的内容类型为application/x-www-form-urlencoded function requestUrl($url,$datanull,$httpstrue,$methodpost){//1.初始化url$ch curl_init($url);//2.设置相关的参数//字符串不直接输出,进行一个变量的存储curl_setopt($ch, CURLOPT_RETURNTRANSFER, true)…...

RabbitMQ - 死信、TTL原理、延迟队列安装和配置

目录 一、死信交换机 1.1、什么是死信交换机 1.2、TTL 1.2.1、什么是 TTL 1.2.2、通过 TTL 模拟触发死信 二、延迟队列 2.1、什么是延迟队列 2.2、配置延迟队列插件 2.2.1、延迟队列配置 a&#xff09;下载镜像 b&#xff09;运行容器 c&#xff09;刚刚设定的Rabb…...

大数据与云计算实验一

检查是否开启 sudo service docker status 开启服务 sudo service docker start 运行服务 sudo docker run -itd -p 8080:80 nginx 查询ID docker ps -all 进入容器shell sudo docker exec -it <容器ID或容器名称> /bin/bash 找到/usr/share/nginx/html/index.…...

实施主品牌进化战略(一):确立主品牌进化架构

主品牌进化战略&#xff0c;即以主品牌为核心创造、巩固、转化竞争优势应对竞争环境变化&#xff0c;避免衰退&#xff0c;回归增长&#xff0c;让主品牌进化的方法论体系。主品牌进化战略制定要从 4 个方面出发&#xff1a;确立主品牌进化架构、更新和明确主品牌竞争方向、建立…...

linux搭建单机ES,集成ik分词器,文本抽取,Kibana可视化平台

Elasticsearch单机&#xff08;Linux&#xff09; 准备工作 第一项&#xff1a; 创建运行Elasticsearch和Kibana专用的普通用户&#xff0c;因为 elasticsearch 和 kibana 不允许使用 root用户启动&#xff0c;所以需要创建新用户启动。 linux用root权限创建一个用户赋权即可…...

金融和大模型的“两层皮”问题

几年前&#xff0c;我采访一位产业专家&#xff0c;他提到了一个高科技到产业落地的主要困惑&#xff1a;两层皮。 一些特别牛的技术成果在论文上发表了&#xff0c;这是一层皮。企业的技术人员&#xff0c;将这些成果产品化、商品化的时候&#xff0c;可能出于工程化的原因&am…...

智能生活从这里开始:数字孪生驱动的社区

数字孪生技术&#xff0c;这个近年来备受瞩目的名词&#xff0c;正迅速渗透到社区发展领域&#xff0c;改变着我们居住的方式、管理的方式以及与周围环境互动的方式。它不仅仅是一种概念&#xff0c;更是一种变革&#xff0c;下面我们将探讨数字孪生技术如何推动社区智能化发展…...

Python计算机二级知识点整理

1.当一个进程在运行过程中释放了系统资源后要调用 唤醒进程原语 唤醒进程原语是把进程从等待队列里移出到就绪队列并设置进程为就绪状态&#xff0c;当一个进程在运行过程中释放了系统资源后进入就绪状态&#xff0c;调用唤醒进程原语。 2. 3. 4.在希尔排序法中&#x…...

双系统ubuntu20.04(neotic版本)从0实现Gazebo仿真slam建图

双系统ubuntu20.04(neotic版本)从0实现Gazebo仿真slam建图 昨晚完成了ROS的多机通讯&#xff0c;还没来得及整理相关操作步骤&#xff0c;在进行实际小车的实验之前&#xff0c;还是先打算在仿真环境中进行测试&#xff0c;熟悉相关的操作步骤&#xff0c;计划通过虚拟机&…...

(JavaEE)(多线程案例)线程池 (简单介绍了工厂模式)(含经典面试题ThreadPoolExector构造方法)

线程诞生的意义&#xff0c;是因为进程的创建/销毁&#xff0c;太重了&#xff08;比较慢&#xff09;&#xff0c;虽然和进程比&#xff0c;线程更快了&#xff0c;但是如果进一步提高线程创建销毁的频率&#xff0c;线程的开销就不能忽视了。 这时候我们就要找一些其他的办法…...

单播与多播mac地址

MAC 地址&#xff08;Media Access Control Address&#xff09;是一个用于识别网络设备的唯一标识符。每个网络设备都有一个独特的 MAC 地址&#xff0c;用于在局域网中进行通信。 单播MAC地址&#xff1a;单播MAC地址用于单播通信&#xff0c;即一对一的通信模式。当设备发送…...

反向动力学Ik学习

参考文章&#xff1a;&#xff08;非本人原创&#xff09; 英文原文&#xff1a;Inverse Kinematics Techniques in Computer Graphics: A Survey (andreasaristidou.com) 知乎翻译文章&#xff1a; 【游戏开发】逆向运动学&#xff08;IK&#xff09;详解 - 知乎 (zhihu.co…...

基于Levenberg-Marquardt算法的声源定位matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .................................................................... %ML if (bML1)varxs…...

vscode的Emmet语法失效

解决方案&#xff1a;设置 -> 搜索Emmet -> 勾选 Emmet:Trigger Expansion On Tab和Emmet: Use Inline Completions -> 重启 注&#xff1a;Emmet语法是vscode自带的语法&#xff0c;可以快速生成HTML结构/CSS样式/格式化语法 Emmet语法 参考&#xff1a;关于vscode使…...

堆排序(大根堆)

堆的定义如下&#xff0c;n个关键字序列[1...n]称为堆&#xff0c;当且仅当满足&#xff1a; a(i)>a(2i)且a(i)>a(2i1) 这个为大根堆 a(i)<a(2i)且a(i)<a(2i 1) 这个为小根堆 通过建堆得到大根堆 大根堆 87,45,78,32,17,65,53,9 可以看成 …...

Mybatis学习笔记3 在Web中应用Mybatis

Mybatis学习笔记2 增删改查及核心配置文件详解_biubiubiu0706的博客-CSDN博客 技术栈:HTMLServletMybatis 学习目标: 掌握mybatis在web应用中如何使用 Mybatis三大对对象的作用域和生命周期 关于Mybatis中三大对象的作用域和生命周期、 官网说明 ThreadLocal原理及使用 巩…...

做棋牌网站建设多少钱/360seo优化

咱们先定义一个简单的类&#xff1a;class Vehicle {int passengers;int fuelcap;int mpg;}有了这个模板&#xff0c;就能够用它来建立对象&#xff1a; ---若对对象与类概念模糊的能够看&#xff1a; 对象与类详解Vehicle veh1 new Vehicle();一般把这条语句的动做称之为建立…...

个人网站备案建设方案书/微信搜一搜seo优化

动画实现&#xff1a;首选css3动画&#xff0c;但是有些是不单单使用css动画就能实现的&#xff0c;如下案例&#xff1a; 下拉列表展开和收起&#xff0c;三角图标的切换&#xff1a;列表收起-》展开设置display&#xff1a;none-》block&#xff0c;但是这种没有过渡动画&am…...

网站策划设计招聘/小程序开发框架

作者&#xff1a;朱金灿 来源&#xff1a;https://blog.csdn.net/clever101 将一个Windows程序从32位转为64位程序&#xff0c;出现用户回调期间遇到未经处理的异常的错误&#xff0c;如下图&#xff1a; 经过调试发现是调用GetWindowLong返回为空指针&#xff0c;经过搜索&am…...

浪子做的阿哲喊麦网站多少/北京网站优化页面

在职场中&#xff0c;写日报、周报是工作标配。但是&#xff0c;这也是让很多人感到头疼且抗拒的事情。尤其是项目经理们&#xff0c;明明每天都已经忙得脚不沾地了&#xff0c;哪有时间去写那个啥报&#xff1f;环环总结了几条大家讨厌写周报的原因&#xff0c;看看有没有你&a…...

网站建设ag/百度广告运营

在 https://www.cnblogs.com/mengyu/p/6759671.html 的启示下&#xff0c;解决了乱码问题&#xff0c;在此向作者表示感谢。 至此&#xff0c;困扰我几天的乱码问题和退出问题都解决了&#xff0c;只是处理速度上有点遗憾。 下面是新代码&#xff0c;较原代码多出了两句 rsp.en…...

网站建设的违约责任怎么写/seo的基本工作内容

1.问题 ubuntu18.04自带了python2.7&#xff0c;工作需要安装了其他版本的python&#xff08;anaconda&#xff0c;python3.5&#xff09;。使用中&#xff0c;遇到输入python ****.py时可以正常运行&#xff0c;但是sudo python ***.py时出现包导入错误&#xff1a;ImportErr…...