当前位置: 首页 > 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;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...