当前位置: 首页 > 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…...

联想ThinkPad声卡驱动安装避坑指南:从E470到X1 Carbon的通用解法

ThinkPad声卡驱动安装全攻略&#xff1a;从型号识别到疑难排解 ThinkPad作为商务笔记本的代表&#xff0c;其稳定性和兼容性一直备受推崇。但即便是这样成熟的产品线&#xff0c;声卡驱动问题依然困扰着不少用户——从经典的E470到高端的X1 Carbon&#xff0c;不同机型可能面临…...

LeifHomieLib:ESP32/8266轻量级Homie v3 MQTT设备库

1. LeifHomieLib 项目概述LeifHomieLib 是一个专为 ESP8266 和 ESP32 平台设计的轻量级 Homie v3 协议实现库&#xff0c;其核心目标是为资源受限的物联网边缘节点提供符合 Homie 规范的 MQTT 设备抽象能力。该库并非 Homie v3 标准的全功能实现&#xff0c;而是聚焦于与 openH…...

OpCore-Simplify终极指南:零代码自动化黑苹果EFI配置实战

OpCore-Simplify终极指南&#xff1a;零代码自动化黑苹果EFI配置实战 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在macOS生态之外构建黑苹果系统&…...

开源编解码工具技术选型与实战指南:跨场景应用的H.264解决方案

开源编解码工具技术选型与实战指南&#xff1a;跨场景应用的H.264解决方案 【免费下载链接】openh264 Open Source H.264 Codec 项目地址: https://gitcode.com/gh_mirrors/op/openh264 一、价值定位&#xff1a;为什么开源编解码工具是技术选型的最优解 在视频技术快…...

UG模型转STP后总出问题?可能是STEP 203和214版本没选对

UG模型转STP格式的深度选择指南&#xff1a;STEP 203与214版本差异解析 在工业设计领域&#xff0c;UG NX与STP格式的转换堪称日常操作&#xff0c;但许多工程师都曾遭遇这样的困境&#xff1a;明明转换过程一切顺利&#xff0c;接收方打开文件时却出现面片丢失、PMI信息异常甚…...

5分钟搞定局域网IP扫描:OpUtils保姆级配置教程(附常见问题排查)

5分钟搞定局域网IP扫描&#xff1a;OpUtils保姆级配置教程&#xff08;附常见问题排查&#xff09; 办公室里突然断网了&#xff1f;打印机死活连不上&#xff1f;新同事的电脑无法接入内网&#xff1f;作为中小企业IT运维人员&#xff0c;这些场景你一定不陌生。别急着打电话求…...

Wan2.2-I2V-A14B部署教程:系统盘50GB+数据盘40GB最小化配置实操

Wan2.2-I2V-A14B部署教程&#xff1a;系统盘50GB数据盘40GB最小化配置实操 1. 镜像概述与核心特性 Wan2.2-I2V-A14B是一款专为文生视频任务优化的私有部署镜像&#xff0c;特别针对RTX 4090D 24GB显存显卡进行了深度优化。这个镜像最大的特点是开箱即用&#xff0c;内置了完整…...

Multisim电路设计避坑指南:红绿灯项目里那些容易忽略的时序与驱动问题

Multisim电路设计避坑指南&#xff1a;红绿灯项目里那些容易忽略的时序与驱动问题 当你第一次在Multisim中完成红绿灯控制电路的设计时&#xff0c;那种成就感确实令人兴奋。但很快&#xff0c;你可能就会遇到一些令人头疼的问题&#xff1a;黄灯闪烁频率不稳定、倒计时显示乱跳…...

智慧生鲜配送:揭秘生鲜配送商城APP功能版块设计

在数字化消费浪潮中&#xff0c;生鲜配送商城APP成为居民采购食材的重要渠道。其功能版块设计聚焦用户需求&#xff0c;通过智能化、便捷化的操作体验&#xff0c;打造高效生鲜购物场景。以下揭秘其核心功能玩法&#xff0c;解析如何实现“从指尖到餐桌”的流畅服务。一、首页&…...

别再死记硬背Sarsa公式了!用Python手搓一个‘胆小’的迷宫探索AI(附完整代码)

用Python打造胆小如鼠的迷宫AI&#xff1a;Sarsa算法实战图解 当你在迷宫中小心翼翼地贴着墙走&#xff0c;生怕掉进陷阱时——恭喜&#xff0c;你已经理解了Sarsa算法的核心思想。今天我们不谈枯燥的数学公式&#xff0c;而是用Python构建一个会"瑟瑟发抖"的迷宫探索…...