SpringBoot整合Minio

SpringBoot整合Minio

在企业开发中,我们经常会使用到文件存储的业务,Minio就是一个不错的文件存储工具,下面我们来看看如何在SpringBoot中整合Minio

POM

pom文件指定SpringBoot项目所依赖的软件工具包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zsxq</groupId><artifactId>csg_idc_zsxq</artifactId><version>0.0.1-SNAPSHOT</version><name>csg_idc_zsxq</name><description>csg_idc_zsxq</description><properties><java.version>17</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.3</spring-boot.version></properties><dependencies><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>3.5.1</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>3.5.1</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.12</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.7.7</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.16</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.12</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.26</version></dependency><!--minio--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.0.3</version></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>17</source><target>17</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.idc.zsxq.CsgIdcZsxqApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>

YML

SpringBoot配置文件

server:port: 11112
# springdoc-openapi项目配置
knife4j:enable: truesetting:language: zh_cn
spring:redis:password:host: 127.0.0.1port: 6379username:
# minio
minio:endpoint: http://127.0.0.1:9000accessKey: minioadminsecretKey: minioadminbucketName: bucket

MinioClientConfig

Minio的配置类

package com.idc.zsxq.config;import io.minio.MinioClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Data
@Component
public class MinIoClientConfig {@Value("${minio.endpoint}")private String endpoint;@Value("${minio.accessKey}")private String accessKey;@Value("${minio.secretKey}")private String secretKey;/*** 注入minio 客户端** @return*/@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}}

MinioUtil

操作Minio的工具类,实现了判断Bucket是否存在,创建Bucket,上传文件,下载文件等功能

package com.idc.zsxq.util;import com.idc.zsxq.model.ObjectItem;
import io.minio.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;/*** @description: minio工具类* @version:3.0*/
@Component
public class MinioUtil {@Resourceprivate MinioClient minioClient;@Value("${minio.bucketName}")private String bucketName;/*** description: 判断bucket是否存在,不存在则创建** @return: void*/public void existBucket(String name) {try {boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());if (!exists) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());}} catch (Exception e) {e.printStackTrace();}}/*** 创建存储bucket** @param bucketName 存储bucket名称* @return Boolean*/public Boolean makeBucket(String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 删除存储bucket** @param bucketName 存储bucket名称* @return Boolean*/public Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** description: 上传文件** @param multipartFile* @return: java.lang.String*/public List<String> upload(MultipartFile[] multipartFile) {List<String> names = new ArrayList<>(multipartFile.length);for (MultipartFile file : multipartFile) {String fileName = file.getOriginalFilename();String[] split = fileName.split("\\.");if (split.length > 1) {fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];} else {fileName = fileName + System.currentTimeMillis();}InputStream in = null;try {in = file.getInputStream();minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(in, in.available(), -1).contentType(file.getContentType()).build());} catch (Exception e) {e.printStackTrace();} finally {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}}names.add(fileName);}return names;}/*** description: 上传文件流** @param in* @return: InputStream*/public void upload(InputStream in, String bucketName, String fileName) {try {minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(in, in.available(), -1).contentType("application/octet-stream;charset=UTF-8").build());} catch (Exception e) {e.printStackTrace();} finally {try {in.close();} catch (IOException e) {e.printStackTrace();}}}/*** description: 下载文件** @param fileName* @return: org.springframework.http.ResponseEntity<byte [ ]>*/public ResponseEntity<byte[]> download(String fileName, String bucketName) {ResponseEntity<byte[]> responseEntity = null;InputStream in = null;ByteArrayOutputStream out = null;try {in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());out = new ByteArrayOutputStream();IOUtils.copy(in, out);//封装返回值byte[] bytes = out.toByteArray();HttpHeaders headers = new HttpHeaders();try {headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();}//需要设置此属性,否则浏览器默认不会读取到响应头中的Accept-Ranges属性,因此会认为服务器端不支持分片,所以会直接全文下载headers.add("Access-Control-Expose-Headers", "Accept-Ranges,Content-Range");headers.setContentLength(bytes.length);headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);headers.setAccessControlExposeHeaders(Arrays.asList("*"));responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);} catch (Exception e) {e.printStackTrace();} finally {try {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}if (out != null) {out.close();}} catch (IOException e) {e.printStackTrace();}}return responseEntity;}/*** 查看文件对象** @param bucketName 存储bucket名称* @return 存储bucket内文件对象信息*/public List<ObjectItem> listObjects(String bucketName) {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());List<ObjectItem> objectItems = new ArrayList<>();try {for (Result<Item> result : results) {Item item = result.get();ObjectItem objectItem = new ObjectItem();objectItem.setObjectName(item.objectName());objectItem.setSize(item.size());objectItems.add(objectItem);}} catch (Exception e) {e.printStackTrace();return null;}return objectItems;}/*** 批量删除文件对象** @param bucketName 存储bucket名称* @param objects    对象名称集合*/public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());return results;}}

案例

在SpringBoot中如何使用MinioUtil操作Minio,一般我们会使用Minio当做文件缓存

下面这个案例实现了下载文件的功能,逻辑:先从Minio查找是否存在文件,如果存在则从Minio下载文件,如果不存在则从远程文件服务器下载文件

//获取文件
public byte[] downloadFile(String bucketName, String fileId, String newFileId) {log.info("下载文件 开始");// 测试bucketName = "library";fileId = "6cc750db08c943b48a259020ce4e6794";newFileId = "0fe8cb9eb5954cc2876c3ac8496692a7";String fileName = bucketName + "_" + fileId + "_" +(newFileId == null ? "" : newFileId);log.info("文件名 {}", fileName);try {//如果没有bucket,则创建minioUtil.existBucket(bucketName);//判断Minio中是否有该文件List<ObjectItem> objectItems = minioUtil.listObjects(bucketName);boolean flag = false;if (CollectionUtil.isNotEmpty(objectItems)) {for (ObjectItem o : objectItems) {if (StringUtils.equals(o.getObjectName(), fileName)) {flag = true;break;}}}byte[] bytes = null;//如果有,则从Minio中获取文件if (flag) {log.info("从Minio获取文件");ResponseEntity<byte[]> download = minioUtil.download(fileName, bucketName);bytes = download.getBody();} else {log.info("从文件服务器获取文件");//如果Minio没有,则从文件服务器获取文件,如果报错,则抛出异常//封装基本查询参数urlString withParamsUrl = CnkiUrlEnum.DOWNLOAD_FILE.getUrl() + "?fileId=" + fileId +(StringUtils.isEmpty(newFileId) ? "" : "&newFileId=" + newFileId) +"&bucketName=" + bucketName;HttpResponse httpResponse = HttpRequest.post(withParamsUrl).header("accessToken", ConstantEnum.TOKEN.getValue()).body("").execute();String status = httpResponse.getStatus() + "";//判断是否请求成功if (!"200".equals(status) && !"204".equals(status)) {log.error("数据库查询异常, CNKI接口返回状态码为:" + status);throw new BusinessException(ResultEnum.ERROR);}//空文件抛出异常if (StringUtils.equals(httpResponse.header("Content-Type"), "application/json")) {String jsonBody = httpResponse.body();JSONObject dataJson = JSONObject.parseObject(jsonBody);String dataCode = dataJson.getString("code");log.error("文件内容为空 : " + dataCode);throw new BusinessException(ResultEnum.ERROR);}//获取文件字节流bytes = httpResponse.bodyBytes();//写入MiniominioUtil.upload(new ByteArrayInputStream(bytes), bucketName, fileName);}log.info("下载文件 结束");//写到响应流中return bytes;} catch (Exception e) {log.error("下载文件报错 : {}", e);}return new byte[]{};}

效果

通过postman调用接口,返回文件流

image-20230815101451026

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/93201.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Android Studio】 win11 安装配置 jdk17 超详细

概述 一个好的安装教程能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径&#xff0c;学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成长。 一、下载JDK JDK官网 这里下载 JDK17 windows x64 installer 二、安装JDK 双击打开下载的 j…

上山取石&#xff0c;下江取锦。诗人秋浦啸傲&#xff0c;新津樵唱。江南山水秀美&#xff0c;水乡文化流长。而水&#xff0c;则是这些山水风景的灵魂所在。 水&#xff0c;雨露滋润万物生长的泉源。 它潺潺流淌于山间溪涧&#xff0c;涓涓细流化成了青山的眼泪。水顺势而下&a…

互联网发展历程:跨越远方,路由器的启示

互联网的蓬勃发展&#xff0c;一直在追求更广阔的连接&#xff0c;更遥远的距离。然而&#xff0c;在早期的网络中&#xff0c;人们面临着连接距离有限的问题。一项重要的技术应运而生&#xff0c;那就是“路由器”。 连接受限的问题&#xff1a;距离有限 早期的网络受限于直接…

认识excel篇3之数据的有效性(数据验证)

数据有效性不仅能够对单元格的输入数据进行条件限制&#xff0c;还可以在单元格中创建下拉列表菜单方便用户选择输入。如果没有做数据验证&#xff0c;单元格内默认可以输入任意类型的数据。数据验证就是限制单元格输入数据&#xff08;必须输入符合要求的才能输入&#xff09;…

基于Prometheus监控Kubernetes集群

目录 一、环境准备 1.1、主机初始化配置 1.2、部署docker环境 二、部署kubernetes集群 2.1、组件介绍 2.2、配置阿里云yum源 2.3、安装kubelet kubeadm kubectl 2.4、配置init-config.yaml 2.5、安装master节点 2.6、安装node节点 2.7、安装flannel、cni 2.8、部署测…

[机器学习]特征工程:特征降维

特征降维 1、简介 特征降维是指通过减少特征空间中的维度&#xff0c;将高维数据映射到一个低维子空间的过程。 在机器学习和数据分析中&#xff0c;特征降维可以帮助减少数据的复杂性、降低计算成本、提高模型性能和可解释性&#xff0c;以及解决维度灾难等问题。特征降维通…

中远麒麟堡垒机 SQL注入漏洞复现

0x01 产品简介 中远麒麟依托自身强大的研发能力,丰富的行业经验&#xff0c;自主研发了新一代软硬件一体化统一安全运维平台一-iAudit 统一安全运维平台。该产品支持对企业运维人员在运维过程中进行统一身份认证、统一授权、统一审计、统一监控&#xff0c;消除了传统运维过程中…

ORCA优化器浅析——CDXLScalar Base class for representing scalar DXL operators

CDXLScalar类作为Base class for representing scalar DXL operators&#xff0c;该类只是定义一些接口&#xff0c;其中实现了GetDXLOperatorType函数&#xff0c;其返回EdxloptypeScalar&#xff0c;代表scalar DXL operators。 class CDXLScalar : public CDXLOperator{ pr…

nodejs+vue+elementui膳食营养健康网站 4d8g9

前端nodejsvueelementui, 后台主要功能是&#xff1a;首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;膳食类型管理&#xff0c;膳食信息管理&#xff0c;膳食食材管理&#xff0c;食材类型管理&#xff0c;我的收藏管理&#xff0c;网站管理&#xff0c;订单管理等…

2023机械制造ERP管理软件哪个好?亿发现代化ERP系统建设,免费更新

机械制造行业市场大&#xff0c;不但需要满足传统行业的需求&#xff0c;还有新能源汽车、智能家居、装备制造等新兴领域的需求。而随着人工智能、物联网、大数据等科技的应用&#xff0c;机械制造业正逐步向智能化、自动化方向发展&#xff0c;增强生产效率和产品质量。在机械…

PHP使用phpmailer及SMTP服务实现邮件发送

博客升级中&#xff0c;把之前没有想到的功能一点点的完善。 这篇日志记录一下&#xff0c;使用phpmailer实现邮件发送的这样一个操作。 博客偶尔会有留言和评论&#xff0c;我也会及时回复&#xff0c;但是有一个问题&#xff0c;我回复了&#xff0c;给我留言的人如果不再次…

大模型是什么?大模型可以在哪些场景应用落地?

大模型是什么&#xff1f;大模型是指模型具有庞大的参数规模和复杂程度的机器学习模型。在深度学习领域&#xff0c;大模型通常是指具有数百万到数十亿参数的神经网络模型。 大模型是指模型具有庞大的参数规模和复杂程度的机器学习模型。在深度学习领域&#xff0c;大模型通常是…

iphone拷贝照片中间带E自动去重软件,以及java程序如何打包成jar和exe

文章目录 一、前提二、问题描述三、原始处理方式四、程序处理4.1 java程序如何打包exe4.1.1 首先打包jar4.1.2 开始生成exe4.1.3 软件使用方式 4.2 更换图标4.2.1 更换swing的打包jar图标4.2.2 更换exe图标 4.3 如何使生成的exe在没有java环境的电脑上运行4.3.1 Inno Setup打包…

pytorch安装VAE项目详解

安装VAE项目 一、 基本环境二、代码来源三、搭建conda环境四、下载数据集五、启动项目六、其他相关问题 一、 基本环境 工具版本号OSwin 11pycharm2020.1GPU3050 二、代码来源 github地址为&#xff1a; https://github.com/AntixK/PyTorch-VAE/blob/8700d245a9735640dda458d…

微信小程序前后端开发快速入门(完结篇)

这篇是微信小程序前后端快速入门完结篇了&#xff0c;今天利用之前学习过的所有知识做一个新的项目「群登记助手v1.0」小程序。 整体技术架构&#xff1a;小程序原生前端小程序云开发。 经历了前面教程的学习&#xff0c;大家有了一定的基础&#xff0c;所以本次分享重心主要是…

气象监测站:用科技感知气象变化

气象监测站是利用科学技术感知当地小气候变化情况的气象观测仪器&#xff0c;可用于农业、林业、养殖业、畜牧业、环境保护、工业等多个领域&#xff0c;提高对环境数据的利用率&#xff0c;促进产业效能不断提升。 气象监测站主要由气象传感器、数据传输系统、电源系统、支架…

CKZF-D60170、CKZF-D70190、CKZF-D80210单向离合器

CKZF-C30100、CKZF-C35110、CKZF-C40125、CKZF-C45130、CKZF-C50150、CKZF-C55160、CKZF-C60170、CKZF-C70190、CKZF-C80210、CKZF-C90230、CKZF-C100270、CKZF-C130310、CKZF-B30100、CKZF-B35110、CKZF-B40125、CKZF-B45130、CKZF-B50150、CKZF-B55160、CKZF-B60170、CKZF-B7…

深入学习前端开发,掌握HTML、CSS、JavaScript等技术

课程链接&#xff1a; 链接: https://pan.baidu.com/s/1WECwJ4T8UQfs2FyjUMbxig?pwdi654 提取码: i654 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --来自百度网盘超级会员v4的分享 课程介绍&#xff1a; 第1周&#xff1a;HTML5基础语法与标签 &#x1f…

【数据结构】二叉树

完全二叉树 是指所有结点度数小于等于2的树 所以这种情况也是&#xff1a; 几条性质 一个具有n个结点的完全二叉树的深度为&#xff1a; log ⁡ 2 ( n 1 ) 的结果向上取整。 \\\log_{2}(n1) \ \ 的结果向上取整。 log2​(n1) 的结果向上取整。设度为0的结点个数是n0&#…

【数据结构】实现顺序表

目录 一.介绍顺序表二.实现顺序表1.创建多文件2.顺序表的存储方式3.函数的声明4.初始化顺序表5.清理顺序表6.打印顺序表7.扩容8.尾插8.尾删9.头插10.头删11.查找12.修改13.在pos位置插入13.在pos位置删除 三.全部代码1.SeqList.h2.SeqList.c3.Test.c 一.介绍顺序表 顺序表是用…