spring boot 整合 minio存储 【使用篇】

导入依赖

		<!--minio--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.0.3</version></dependency>

yml配置(默认配置)

max-file-size: 200MB 设置文件最大上传大小为200MB,超过则返回错误信息并拒绝文件上传

max-request-size: 100MB 这个配置项指定了整个请求的最大大小限制,包括所有文件和表单数据的大小。如果请求大小超过这个限制,将会拒绝请求并返回错误。

enabled:true 这个配置项指定了文件上传功能是否启用,设置为true表示启用文件上传功能,设置为false表示禁用文件上传功能。当禁用文件上传功能时,任何文件上传请求都将被拒绝。

minion的配置和oss很像,都是这几个需要注入的值

spring:# 配置文件上传大小限制servlet:multipart:max-file-size: 200MBmax-request-size: 200MBenabled: true
minio:endpoint: http://127.0.0.1:9000accessKey: minioadminsecretKey: minioadminbucketName: bucket-qhj

该图和上面minio配置对应

补充:由于每次启动minio.exe要进入对应目录,很麻烦,所以可以写个批处理文件.bat

  1. @echo off:这是批处理文件的第一行,表示关闭命令回显,即不在命令执行前显示命令本身。

  2. echo.:显示一个空行,这样可以让输出信息更加清晰。

  3. echo [信息] 运行MinIO文服务器。:输出提示信息,告诉用户即将运行MinIO文服务器。

  4. title minio:设置窗口标题为 "minio"。

  5. D:  代表进入D盘

  6. cd D:\Program Files\minio 代表进入你minio.exe存放的根目录

    minio.exe server D:\MineFile\zuoye\xm\minioFile --console-address ":9999" 在D:\MineFile\zuoye\xm\minioFile文件夹执行,并且增加额外端口’9999‘

@echo off
echo.
echo [信息] 运行MinIO文服务器。
echo.title minioD:
cd D:\Program Files\miniominio.exe server D:\MineFile\zuoye\xm\minioFile --console-address ":9999"
pause

配置类

注入客户端配置放入bean

@Data注解:

        自动生成java类的标准方法,getter,setter,toString,equals,hashCode方法等

@Component

        这个注解标识 MinIoClientConfig 类作为一个组件(bean)交给 Spring 容器管理,这样其他地方就可以通过依赖注入来使用该类。

value注解

        装配yml配置文件中的值

@Bean注解

        把minioClient方法注入容器交给 Spring 容器管理

@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();}}

实体类

用于工具类的调用暂存

@Data
public class ObjectItem {private String objectName;private Long size;
}

工具类

根据实体类

/*** @description: minio工具类* @version:3.0*/
@Component
public class MinioUtilS {@Autowiredprivate 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 fileName* @return: org.springframework.http.ResponseEntity<byte [ ]>*/public ResponseEntity<byte[]> download(String fileName) {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();}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;}
}

控制器类

返回可访问的url

@RestController:

         这个注解表示该类是一个 RESTful 服务的控制器,用于处理 HTTP 请求并返回 JSON 格式的响应。

@Slf4j:

        这是 lombok 提供的注解,用于自动生成日志 Logger 对象,可以通过 log 对象进行日志输出。

@RestController
@Slf4j
@RequestMapping("/fileSave")
public class MinioController {@Autowiredprivate MinIoUtil minIoUtil;@Autowiredprivate MinioUtilS minioUtilS;@Value("${minio.endpoint}")private String address;@Value("${minio.bucketName}")private String bucketName;@RequestMapping("/fileInMinio")public R uploadInMinio(MultipartFile file) {List<String> upload = minioUtils.upload(new MultipartFile[]{file});String url = address + "/" + bucketName + "/" + upload.get(0);return R.ok().put("filePath", url);}}

上传后获取链接为

访问报错

解决方式

来到minio控制台

打开你正在使用的bucket

修改访问权限为public就行

重新访问链接,应该就能查看

前端代码

通过父组件导入子组件,注册子组件,引用子组件弹出

父组件调用方法

    // 文件导入importExcel () {this.uploadFileVisible = truethis.$nextTick(() => {this.$refs.uploadFile.init()})}

 子组件vue页面

包含三种上传方式的切换

<template><el-dialogtitle="维修处理":close-on-click-modal="true":visible.sync="visible"><el-selectsize="small"v-model="uploadMethodValue"placeholder="请选择上传方式"clearable=""filterable><el-optionv-for="d in uploadMethod":key="d.value":label="d.name":value="d.value"></el-option></el-select><el-uploadclass="upload-demo"ref="upload"dragaction="#":on-change="handleChangeSelect":on-exceed="handleExceed":file-list="fileList":limit="1"multiple:auto-upload="false"><i class="el-icon-upload"></i><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><divclass="el-upload__tip"slot="tip">只能上传jpg/png文件,且不超过500kb</div><divclass="el-upload__tip"slot="tip">访问路径:{{ filePath }}</div></el-upload></el-dialog>
</template><script>
export default {data () {return {// 对话框显示状态visible: false,uploadMethod: [{ name: '本地存储', value: '1' },{ name: 'oss存储', value: '2' },{ name: 'miniio', value: '3' }],// 选中的上传方式uploadMethodValue: '',// 表单数据dataForm: {},filePath: '',fileList: []}},methods: {// 初始化方法init () {this.visible = truethis.filePath = ''},// 文件超出个数提示handleExceed (files, fileList) {this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)},handleChangeSelect (file) {if (this.uploadMethodValue === '1') {// 本地存储this.handleChange(file, '/fileSave/file')} else if (this.uploadMethodValue === '2') {// oss存储this.handleChange(file, '/fileSave/fileInOSS')} else if (this.uploadMethodValue === '3') {// miniiothis.handleChange(file, '/fileSave/fileInMinio')}},handleChange (file, urlSelect) {let formData = new FormData()formData.append('file', file.raw) // 传文件this.$http({url: this.$http.adornUrl(urlSelect),method: 'post',data: formData,headers: {'Content-Type': 'multipart/form-data'}}).then(({ data }) => {if (data && data.code === 0) {this.filePath = data.filePaththis.$message({message: '操作成功',type: 'success',duration: 1500})} else {this.$message.error(data.msg)}this.$refs.upload.clearFiles() // 清除文件})}}
}</script>

拓展学习

MultipartFile

 MultipartFile为org.springframework.web.mutipart包下的一个类,也就是说如果想使用MultipartFile这个类就必须引入spring框架,换句话说,如果想在项目中使用MultipartFile这个类,那么项目必须要使用spring框架才可以,否则无法引入这个类。

一般来讲使用MultipartFile这个类主要是来实现以表单的形式进行文件上传功能。

MiltipartFile类注释说明

 第一句:一种可以接收使用多种请求方式来进行上传文件的代表形式。也就是说,如果你想用spring框架来实现项目中的文件上传功能,则MultipartFile可能是最合适的选择,而这里提到的多种请求方式则可以通俗理解为以表单的形式提交。

      第二句:这个文件内容可以存储到内存中或者存储在磁盘的临时位置上。

      第三句:无论发生哪种情况,用户都可以自由地拷贝文件内容到session存储中,或者以一种永久存储的形式进行存储,如果有需要的话。

      第四句:这种临时性的存储在请求结束之后将会被清除掉。

类中方法

 getName方法

获取的是前后端约定的传入文件的参数的名称,在SpringBoot后台中则是通过@Param("uploadFile") 注解定义的内容。

getOriginalFileName方法 

getOriginalFileName方法获取的是文件的完整名称,包括文件名称+文件拓展名。

getContentType方法 

getContentType方法获取的是文件的类型,注意是文件的类型,不是文件的拓展名。

getBytes方法 

getBytes方法用来将文件转换成一种字节数组的方式进行传输,会抛出IOException异常。

getInputStream方法 

getInputStream方法用来将文件转换成输入流的形式来传输文件,会抛出IOException异常。

transferTo方法 

transferTo方法用来将接收文件传输到给定目标路径,会抛出IOException、IllegalStateException异常。该方法在实际项目开发中使用较少。

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

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

相关文章

华为od机试C卷-开源项目热度榜单

1、题目描述 某个开源社区希望将最近热度比较高的开源项目出一个榜单&#xff0c;推荐给社区里面的开发者。 对于每个开源项目&#xff0c;开发者可以进行关注(watch)、收藏(star)、fork、提issue、提交合并请求(MR)等。 数据库里面统计了每个开源项目关注、收藏、fork、issue…

微服务API网关---APISIX

最近在做微服务调研&#xff0c;看到了apisix这个网关&#xff0c;于是进行了初步了解一下。 微服务是指&#xff0c;将大型应用分解成多个独立的组件&#xff0c;其中每个组件都各自的负责对应项目。 系统的架构大致经历了&#xff1a;单体应用架构–> SOA架构 -->微服务…

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 附录D 关于TCP并发连接的几个思考题与试验

前几天作者在新浪微博上出了两道有关TCP的思考题&#xff0c;引发了一场讨论&#xff08;http://weibo.com/1701018393/eCuxDrtaONn&#xff09;。 第一道初级题目是&#xff1a;有一台机器&#xff0c;它有一个IP&#xff0c;上面运行了一个TCP服务程序&#xff0c;程序只侦听…

StarRocks实战——松果出行实时数仓实践

目录 一、背景 二、松果出行实时OLAP的演进 2.1 实时数仓1.0的架构 2.2 实时数仓2.0的架构 2.3 实时数仓3.0的架构 三、StarRocks 的引入 四、StarRocks在松果出行的应用 4.1 在订单业务中的应用 4.2 在车辆方向的应用 4.3 StarRocks “极速统一” 落地 4.4 StarRoc…

分布式ID生成系统之雪花算法详解

在当今的云计算和微服务架构盛行的时代&#xff0c;分布式系统已成为软件开发的重要组成部分。随着系统规模的扩大和业务的复杂化&#xff0c;对数据一致性和唯一性的要求也越来越高&#xff0c;尤其是在全局唯一标识符&#xff08;ID&#xff09;的生成上。因此&#xff0c;分…

yolov5训练太慢的解决方案

问题原因 训练太慢大多是因为没有安装CUDA和pytorch&#xff0c;导致的只有cpu在跑&#xff0c;显卡没跑 这就是很典型的。 解决方案 第一步&#xff1a;安装CUDA 在本机上面安装CUDA,记住只有N卡可以安装&#xff0c;一开始的电脑是自带CUDA的。 如果不是自带的CUDA&…

求数字的每一位之和

求数字的每一位之和 题目描述&#xff1a;解法思路&#xff1a;解法代码&#xff1a;运行结果&#xff1a; 题目描述&#xff1a; 输入一个整数m&#xff0c;求这个整数m的每⼀位之和&#xff0c;并打印。 测试1&#xff1a; 输⼊&#xff1a;1234 输出&#xff1a;10 测试2&…

土壤侵蚀量化评估

根据之前的文章,已经算出了R、K、LS、C、P 现在计算土壤侵蚀,将几个前期制作好的因子的TIFF文件,用栅格计算器相乘 发现局部地区存在轻度侵蚀,大部分区域是微度侵蚀 然后对比了一下范围 其中的几个因子都在文献范围内,说明计算结果并未出错,可能就是研究区正常范围和结…

6020一拖二快充线:手机充电的革命性创新

在快节奏的现代生活中&#xff0c;手机已不仅仅是一个通讯工具&#xff0c;更是我们工作、学习和娱乐的得力助手。然而&#xff0c;手机的电量问题一直是困扰着我们的难题。为了解决这个问题&#xff0c;市场上出现了一种名为“一拖二快充线”的充电设备&#xff0c;它不仅具备…

八. 实战:CUDA-BEVFusion部署分析-分析BEVFusion中各个ONNX

目录 前言0. 简述1. camera.backbone.onnx(fp16)2. camera.backbone.onnx(int8)3. camera.vtransform.onnx(fp16)4. fuser.onnx(fp16)5. fuser.onnx(int8)6. lidar.backbone.xyz.onnx7. head.bbox.onnx(fp16)总结下载链接参考 前言 自动驾驶之心推出的《CUDA与TensorRT部署实战…

Unity UGUI之Scrollbar基本了解

Unity的Scrollbar组件是用于在UI中创建滚动条的组件之一。滚动条通常与其他可滚动的UI元素&#xff08;如滚动视图或列表&#xff09;一起使用&#xff0c;以便用户可以在内容超出可见区域时滚动内容。 以下是Scrollbar的基本信息和用法: 1、创建 在Unity的Hierarchy视图中右…

jetson nano——编译安装opencv==4.4

目录 1.下载源码&#xff0c;我提供的链接如下&#xff1a;1.1文件上传的路径位置&#xff0c;注意ymck是我自己的用户名&#xff08;你们自己换成你们自己相对应的就行&#xff09; 2.解压文件3.安装依赖4.增加swap交换内存4.1临时增加交换内存swap4.2永久增加swap 5.安装open…

2024-03-03 作业

作业要求&#xff1a; 1.使用fwrite、fread将一张随意的bmp图片&#xff0c;修改成德国的国旗 2.使用提供的getch函数&#xff0c;编写一个专门用来输入密码的函数&#xff0c;要求输入密码的时候&#xff0c;显示 * 号&#xff0c;输入回车的时候&#xff0c;密码输入结束 作业…

【MySQL】索引(重点)-- 详解

一、索引 没有索引&#xff0c;可能会有什么问题&#xff1f; 索引 &#xff1a;提高数据库的性能&#xff0c;索引是物美价廉的东西了。不用加内存&#xff0c;不用改程序&#xff0c;不用调 sql &#xff0c;只要执行正确的 create index &#xff0c;查询速度就可能提高成…

加密与安全_探索数字证书

文章目录 Pre概述使用keytool生成证书使用Openssl生成证书 &#xff08;推荐&#xff09;证书的吊销小结 Pre PKI - 借助Nginx 实现Https 服务端单向认证、服务端客户端双向认证 PKI - 04 证书授权颁发机构&#xff08;CA&#xff09; & 数字证书 PKI - 数字签名与数字证…

java面试题(spring框架篇)(黑马 )

树形图&#xff1a; 一、Spring框架种的单例bean是线程安全吗&#xff1f; Service Scope("singleton") public class UserServiceImpl implements UserService{ } singleton:bean在每个Spring IOC容器中只有一个实例 protype&#xff1a;一个bean的定义可以有多个…

【Web安全靶场】xss-labs-master 1-20

xss-labs-master 其他靶场见专栏 文章目录 xss-labs-masterlevel-1level-2level-3level-4level-5level-6level-7level-8level-9level-10level-11level-12level-13level-14level-15level-16level-17level-18level-19level-20 level-1 第一关没有进行任何限制&#xff0c;get请求…

pytorch_神经网络构建6

文章目录 强化学习概念实现qLearning基于这个思路,那么解决这个问题的代码如下 强化学习概念 强化学习有一个非常直观的表现&#xff0c;就是从出发点到目标之间存在着一个连续的状态转换&#xff0c;比如说从状态一到状态456&#xff0c;而每一个状态都有多种的行为&#xff…

全国青少年软件编程(Python)等级考试试卷(一级) 测试卷2021年12月

第 1 题 【 单选题 】 下面程序的运行结果是什么&#xff1f;&#xff08; &#xff09; a10 b5 ca*b print(c) A :10 B :15 C :50 D :5 正确答案:C 试题解析: 第 2 题 【 单选题 】 与a>b and b>c等价的是&#xff1f;&#xff08; &#xff09; A…

Libevent的使用及reactor模型

Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff0c;不如 ACE 那么臃肿庞大&#xff1b;源代码相当精炼、易读…