minio + linux + docker + spring boot实现文件上传与下载
minio + docker + spring boot实现文件上传与下载
- 1.在linux上安装并启动docker
- 2.在docker中拉取minio并启动
- 3.Spring Boot 整合 minio
- 4.测试 minio 文件上传、下载及图片预览等功能
1.在linux上安装并启动docker
- 检查linux内核,必须是3.10以上
uname ‐r
- 安装docker
yum install docker
- 启动docker
systemctl start docker
2.在docker中拉取minio并启动
- 搜索镜像
docker search minio
- 拉取镜像
docker pull minio/minio
- 启动minio
docker run -p 9000:9000 -p 9090:9090 --name minio \-d --restart=always \-e MINIO_ACCESS_KEY=vinci \-e MINIO_SECRET_KEY=123456\-v /usr/local/minio/data:/data \-v /usr/local/minio/config:/root/.minio \minio/minio server /data --console-address ":9000" --address ":9090"
-p: 指定端口映射,格式为:主机端口:容器端口 (这里注意要映射两个,否则API会访问不到)
-e “MINIO_ROOT_USER=vinci” minio用户名;
-e MINIO_SECRET_KEY=123456 minio 密码
-d: 后台运行容器,并返回容器ID;
-v: 绑定一个卷
这里可以看到minio已经在docker里启动起来了
接下来我们可以通过以下命令来查看 minio console和minio api 访问端口
docker logs minio
- 访问minio控制台
在此步骤前记得开放端口号
我们接下来可以使用密码和账号登录minio控制台了
3.Spring Boot 整合 minio
在此之前我们可以先通过控制台来创建一个bucket
- 集成minio
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.0</version>
</dependency>
- 编写minio配置类
/*** @package: com.vinci.minio.config* @className: MinioConfig* @author: Vinci* @description: minio配置类* @date: 2023/10/27 13:10*/
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {private String endpoint;private String accessKey;private String secretKey;private String bucketName;@Beanpublic MinioClient minioClient(){return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}}
- 在application.properties中添加以下配置
minio.endpoint=http://108.13.21.28:9090/
minio.bucket-name=images
minio.access-key=xxxxx
minio.secret-key=xxxxx
注意 minio.endpoint 是minio API地址,不是控制台地址
minio.bucket-name 是 bucket的名称
minio.access-key 是用户名
minio.secret-key是密码
- 编写minio工具类
package com.vinci.minio.utils;import com.vinci.minio.config.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;/*** @description: minio工具类* @author: Vinci* @date: 2023/10/27 13:23**/
@Component
@Slf4j
public class MinioUtil {@Resourceprivate MinioConfig config;@Resourceprivate MinioClient minioClient;/*** @description: 查看存储bucket是否存在* @author: Vinci* @date: 2023/10/27 13:24* @param bucketName 要查看的bucket名称* @return 存在即返回true**/public Boolean bucketExists(String bucketName) {try {return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());} catch (Exception e) {log.error("发现异常",e);return false;}}/*** @description: 创建存储bucket* @author: Vinci* @date: 2023/10/27 13:24* @param bucketName 要创建的bucket名称* @return 创建成功即返回true**/public Boolean makeBucket(String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());return true;} catch (Exception e) {log.error("发现异常",e);return false;}}/*** @description: 删除存储bucket* @author: Vinci* @date: 2023/10/27 13:24* @param bucketName 要删除的bucket名称* @return 删除成功即返回true**/public Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());return true;} catch (Exception e) {log.error("发现异常",e);return false;}}/*** @description: 获取全部bucket* @author: Vinci* @date: 2023/10/27 13:24* @return 返回bucket结果集**/public List<Bucket> getAllBuckets() {try {return minioClient.listBuckets();} catch (Exception e) {log.error("发现异常",e);return null;}}/*** @description: 文件上传* @author: Vinci* @date: 2023/10/27 13:24* @param file 表单上传的文件* @return 返回文件上传的路径**/public String upload(MultipartFile file) {String originalFilename = file.getOriginalFilename();if (originalFilename == null || originalFilename.isEmpty()){throw new RuntimeException();}String fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));String objectName = new SimpleDateFormat("yyyyMM").format(new Date()) + "/" + fileName;try {PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(config.getBucketName()).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();minioClient.putObject(objectArgs);return objectName;} catch (Exception e) {log.error("发现异常",e);return null;}}/*** @description: 预览图片* @author: Vinci* @date: 2023/10/27 13:24* @param fileName 文件在bucket中的全路径* @return 返回文件的浏览路径**/public String preview(String fileName){// 查看文件地址GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder().bucket(config.getBucketName()).object(fileName).method(Method.GET).build();try {return minioClient.getPresignedObjectUrl(build);} catch (Exception e) {log.error("发现异常",e);return null;}}/*** @description: 文件下载* @author: Vinci* @date: 2023/10/27 13:24* @param fileName 文件在bucket中的全路径**/public void download(String fileName, HttpServletResponse res) {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(config.getBucketName()).object(fileName).build();try (GetObjectResponse response = minioClient.getObject(objectArgs)){byte[] buf = new byte[1024];int len;try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){while ((len=response.read(buf))!=-1){os.write(buf,0,len);}os.flush();byte[] bytes = os.toByteArray();res.setCharacterEncoding("utf-8");res.setContentType("application/force-download");res.addHeader("Content-Disposition", "inline;fileName=" + fileName);try (ServletOutputStream stream = res.getOutputStream()){stream.write(bytes);stream.flush();}}} catch (Exception e) {log.error("发现异常",e);}}/*** @description: 查看文件对象* @author: Vinci* @date: 2023/10/27 13:24* @return 存储bucket内文件对象信息**/public List<Item> listObjects() {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(config.getBucketName()).build());List<Item> items = new ArrayList<>();try {for (Result<Item> result : results) {items.add(result.get());}return items;} catch (Exception e) {log.error("发现异常",e);return null;}}/*** @description: 删除文件信息* @author: Vinci* @date: 2023/10/27 13:24* @return 删除成功则返回true**/public boolean remove(String fileName){try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(config.getBucketName()).object(fileName).build());return true;}catch (Exception e){log.error("发现异常",e);return false;}}}
4.测试 minio 文件上传、下载及图片预览等功能
- 编写controller通过接口的方式来测试minio功能
package com.vinci.minio.controller;import com.vinci.minio.utils.MinioUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;/*** @package: com.vinci.minio.controller* @className: TestMinioController* @author: Vinci* @description: 测试minio* @date: 2023/10/27 13:48*/
@Controller
@RequestMapping(value = "/minio")
public class TestMinioController {@Resourceprivate MinioUtil minioUtil;/*** @description: 文件上传测试* @author: Vinci* @date: 2023/10/27 13:48**/@ResponseBody@PostMapping("/upload")public String fileUpload(MultipartFile file) {return minioUtil.upload(file);}/*** @description: 文件下载测试* @author: Vinci* @date: 2023/10/27 13:51**/@ResponseBody@GetMapping("/download")public String fileDownload(String fileName, HttpServletResponse response){minioUtil.download(fileName,response);return "success";}/*** @description: 图片预览* @author: Vinci* @date: 2023/10/27 13:53**/@GetMapping("/preview")public String imagePreview(String fileName){return minioUtil.preview(fileName);}}
- 测试文件上传
使用postMan来调用文件上传的接口
我们返回控制台可以看到文件已经上传上去了
- 测试文件下载
我们借助postman工具点击发送并下载可以看到文件下载成功了
- 图片在线预览
我们同样借助postman工具发送请求,我们可以看到返回了图片的在线浏览地址,点击即可在线浏览图片
以上便是minio 整合springboot的全部流程了,感谢阅读!
SpringBoot案例地址:https://gitee.com/vinci99/springboot-minio-test.git
相关文章:

minio + linux + docker + spring boot实现文件上传与下载
minio docker spring boot实现文件上传与下载 1.在linux上安装并启动docker2.在docker中拉取minio并启动3.Spring Boot 整合 minio4.测试 minio 文件上传、下载及图片预览等功能 1.在linux上安装并启动docker 检查linux内核,必须是3.10以上 uname ‐r安装docker…...

vue ant DatePicker 日期选择器 限制日期可控范围
场景 限制当前日期之前不能选择 限制只能选择日期区间内 Ant Design Vue 效果 <a-date-picker :disabledDate"disabledDate"></a-date-picker>method // 限制日期选择disabledDate(current) {return current && current > moment().endOf(&…...
linux 音视频架构 linux音视频开发
linux 音视频架构 linux音视频开发 转载 mob6454cc65110a 2023-07-26 22:27:01 文章标签 linux 音视频架构 ci QT 视频教程 文章分类 架构 后端开发 阅读数117 目录 前言1、软件工具准备a. 录音软件b. 录屏软件c. 摄像头软件d. 安卓屏幕操作软件e. 视频剪辑软件2、视频教…...

el-table添加固定高度height后高度自适应
0 效果 1 添加自定义指令 新建目录src/directive/el-table 在el-table目录下新建文件adaptive.js import { addResizeListener, removeResizeListener } from element-ui/src/utils/resize-event// 设置表格高度const doResize async(el, binding, vnode) > {// 获取表格…...
Python分享之多进程探索 (multiprocessing包)
在初步了解Python多进程之后,我们可以继续探索multiprocessing包中更加高级的工具。这些工具可以让我们更加便利地实现多进程。 进程池 进程池 (Process Pool)可以创建多个进程。这些进程就像是随时待命的士兵,准备执行任务(程序)。一个进程池中可以容…...

Boris FX Mocha Pro 2023:Mac/win全能影像处理神器
Boris FX Mocha Pro 2023是一款广受欢迎的影像处理软件,它凭借其强大的功能和卓越的性能,成为了影视后期、广告制作、动画设计等领域的必备工具。无论您是专业的影视制作人员,还是初入行的新手,Boris FX Mocha Pro 2023都能为您的…...

elementUI 特定分辨率(如1920*1080)下el-row未超出一行却换行
在1920*1080分辨率下, el-col 内容未超出 el-col 宽度,el-col 不足以占据一行,el-row 却自动换行了(其他分辨率没有这个问题)。 截图: 排查: el-col 内容没有溢出;没有多余的 pad…...

mac电脑视频处理推荐:达芬奇DaVinci Resolve Studio 18 中文最新
DaVinci Resolve Studio 18是一款专业的视频编辑、调色和后期制作软件,由Blackmagic Design开发。它被广泛应用于电影、电视和广告等行业,提供了全面的工具和功能,使用户能够进行高质量的影片制作和后期处理。 以下是DaVinci Resolve Studio…...

OKLink携手CertiK在港举办Web3生态安全主题论坛
2023年10月23日,OKLink与CertiK共同发起的Web3生态安全主题论坛在香港铜锣湾拉开帷幕。本次论坛由OKLink和CertiK主办,香港投资推广署独家支持,聚焦如何构建安全可靠的Web3生态系统议题,同时深入剖析这一进程中所面临的潜在挑战。…...

王道p40 1.设计一个递归算法,删除不带头结点的单链表L中的所有值为x的结点(c语言代码实现)图解递归
视频讲解(献丑了):p40 第1题 王道数据结构课后代码题c语言代码实现_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Xa4y1Q7ui/?spm_id_from333.999.0.0 首先它是一个不带头结点的单链表 我们就得特殊处理 我们先让*LNULL; 然后为s开辟一个新…...

深入浅出排序算法之希尔排序
目录 1. 原理 2. 代码实现 3. 性能分析 1. 原理 希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后…...
close excel by keyword 根据关键字关闭 excel 窗口 xlwings 方式实现
根据标题关键字关闭 workbook,如果没有打开的 workbook 则退出 excel xlwings 方式实现 更方便快捷 def close_excel_by_keyword(keyword):if ~$ in keyword:returnapp xw.apps.activefor workbook in app.books:if keyword in workbook.name:workbook.close()fi…...

LIO-SAM算法解析
文章目录 简介算法概述1.点云去畸变1.1 主要功能1.2 主要流程 2.特征提取3.IMU预积分4.地图优化5.算法评估 简介 LIO-SAM在lego-loam的基础上新增了对IMU和GPS的紧耦合,采用一个因子图对位姿进行优化,包括IMU因子,激光里程计因子,…...
vscode 提升小程序开发效率的必备插件与工具
1,微信小程序开发助手(WeChat Snippet):提供了小程序代码片段、模板和快速生成页面的功能,加快了开发速度。 2,小程序助手(Minapp):提供了小程序项目创建、编译、预览和…...
第五章单元测试
一、学习目的与要求 本章对单元测试进行了详细的介绍。通过本章的学习,应掌握单元测试的概念,了解单元测试的误区,掌握单元测试的策略、分析方法和用例设计方法。 二、考核知识点与考核目标 (一)单元测试的概念&#…...

【JAVA基础】多线程与线程池
多线程与线程池 文章目录 多线程与线程池1. 相关概念1.1 线程调度1.2 守护线程 2. 生命周期3. 同步机制/同步锁3.1 synchronized3.2 lock3.3 synchronized 与 Lock 的对比 4. 死锁5. 线程通信5.1 线程间的通信5.2 等待唤醒机制5.3 举例5.4 调用 wait 和 notify 需注意的细节5.5…...

HCIA数据通信——交换机(Vlan间的通信与安全)
前言 之前的提到了交换机的概念和实验。不过交换机的一些功能还没有说完,我们的实验也仅仅是阻止相同地址段的IP地址互通,也没有用到子接口和路由器。显然,那样的配置过于简单。 端口安全 Port Security(端口安全)的功…...

Linux shell编程学习笔记16:bash中的关联数组
上一节我们探讨了普通的数组,即使用数字下标来索引数组中不同的元素的数组,也可以称之为索引数组。 相比纯粹的数字,字符串不仅能表明含义,也更便于记忆使用,于是就有了关联数组。 一、关联数组概述 bash 从4.0开始支…...
浏览器是怎么执行JS的?——消息队列与事件循环
看完渡一的课后,感觉这块内容确实非常重要,写 JS 的连 JS 的执行原理都不知道可不行。 事件循环 在写 JS 的时候,你有没有想过 JS 是按照什么顺序执行的?浏览器是怎么执行 JS 代码的?为什么有时候代码没有按照我们认为…...

IMU预积分的过程详解
一、IMU和相机数据融合保证位姿的有效性: 当运动过快时,相机会出现运动模糊,或者两帧之间重叠区域太少以至于无法进行特征匹配,所以纯视觉SLAM对快速的运动很敏感。而有了IMU,即使在相机数据无效的那段时间内ÿ…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...