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进行上传和下载文件,在此基础上,我们可以使用spring boot集成Minio JAVA SDK,添加自动配置、装配、客户端管理等功能,简化开发 2 Spring Boot集成Minio 2.1 环境搭建 首先我们搭…...
抖音视频下载.py(23年9月份可用)
声明:仅供学习交流使用!!! 抖音无水印视频下载; 首先登录抖音网页端 打开要下载的视频userId 然后编码实现下载 最后是完整代码,拿走就能用那种: # _*_ coding:utf-8 _*_import json import requests import time import randomheaders = """Accept: a…...
项目基本搭建流程
项目创立:webapp 设置maven 的和settings.xml 的地址 手动建立java文件夹和resource文件夹 一.分层 二.使用generator 来自动建立实体类dao 和dao接口,存放sql文件的xml;并复制到项目中(路径可能可以直接设置) 三. 配置文件&…...
学习pytorch11 神经网络-非线性激活
神经网络-非线性激活 官网文档常用1 ReLUinplace 常用2 Sigmoid 代码logs B站小土堆学习pytorch视频 非常棒的up主,讲的很详细明白 官网文档 https://pytorch.org/docs/stable/nn.html#non-linear-activations-weighted-sum-nonlinearity 常用1 ReLU 对输入做截断…...
Jenkins学习笔记2
Jenkins下载安装: 从清华源开源镜像站上下载jenkins的安装包: 安装的是这个版本。 关于软件的版本,尽量使用LTS,长期支持。 首先是安装openjdk: yum install fontconfig java-11-openjdk[rootlocalhost soft]# java …...
自动化测试:yaml结合ddt实现数据驱动!
在pythonunittestseleniumddt的框架中,数据驱动常见有以下几种方式实现: Csv/txtExcelYAML 本文主要给大家介绍测试数据存储在YAML文件中的使用场景。首先先来简单介绍一下YAML。 1. 什么是YAML 一种标记语言类似YAML,它实质上是一种通用…...
高效管理,轻松追踪——Chrono Plus for Mac任务管理工具
Chrono Plus for Mac是一款专注于任务管理和跟踪的应用程序。它提供了一种直观、清晰的界面,使您能够轻松创建、安排和分类任务。无论是个人项目还是团队合作,Chrono Plus都能为您提供一种有效组织和管理任务的方式。 这个应用程序具有多种强大的功能&a…...
python项目2to3方案预研
目录 官方工具2to3工具安装参数解释基本使用工具缺陷 future工具安装参数解释基本使用工具缺陷 python-modernize工具安装参数解释基本使用工具缺陷 pyupgrade工具安装参数解释基本使用工具缺陷 对比 官方工具2to3 2to3 是Python官方提供的用于将Python 2代码转换为Python 3代…...
MongoDB 是什么和使用场景概述(技术选型)
一、从NOSQL(Not Only SQL)说起 常见的数据库可以分为下面的两种类型: RDBMS(关系型数据库):常见的关系型数据库有 Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL;NoSQL(非关系型数据库&a…...
打印 pyspark.sql.dataframe.DataFrame 有哪些列
在 PySpark 中,要打印 pyspark.sql.dataframe.DataFrame 的列,可以使用 columns 属性。以下是一个示例代码: from pyspark.sql import SparkSession# 创建 SparkSession spark SparkSession.builder.getOrCreate()# 假设您的 DataFrame 名称…...
什么是虚拟DOM(Virtual DOM)?它在前端框架中的作用是什么?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是虚拟DOM(Virtual DOM)?⭐ 虚拟DOM 在前端框架中的作用⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦&…...
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自动更新 前言:跟着我的节奏一步一步点下去,就OK 第一步第二步第三步第四步第五步第六步第七步 新建文件第八步 新增文件名称:FlightSettingsMaxPauseDays第九步 设置暂停更新天数第十步 选中你设置的最大值 前言:跟着…...
倒计时列表实现(小程序端Vue)
//rich-text主要用来将展示html格式的,可以直接使用这个标签 <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)下载镜像 b)运行容器 c)刚刚设定的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.…...
实施主品牌进化战略(一):确立主品牌进化架构
主品牌进化战略,即以主品牌为核心创造、巩固、转化竞争优势应对竞争环境变化,避免衰退,回归增长,让主品牌进化的方法论体系。主品牌进化战略制定要从 4 个方面出发:确立主品牌进化架构、更新和明确主品牌竞争方向、建立…...
linux搭建单机ES,集成ik分词器,文本抽取,Kibana可视化平台
Elasticsearch单机(Linux) 准备工作 第一项: 创建运行Elasticsearch和Kibana专用的普通用户,因为 elasticsearch 和 kibana 不允许使用 root用户启动,所以需要创建新用户启动。 linux用root权限创建一个用户赋权即可…...
金融和大模型的“两层皮”问题
几年前,我采访一位产业专家,他提到了一个高科技到产业落地的主要困惑:两层皮。 一些特别牛的技术成果在论文上发表了,这是一层皮。企业的技术人员,将这些成果产品化、商品化的时候,可能出于工程化的原因&am…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
