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,即使在相机数据无效的那段时间内ÿ…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
PLC入门【4】基本指令2(SET RST)
04 基本指令2 PLC编程第四课基本指令(2) 1、运用上接课所学的基本指令完成个简单的实例编程。 2、学习SET--置位指令 3、RST--复位指令 打开软件(FX-TRN-BEG-C),从 文件 - 主画面,“B: 让我们学习基本的”- “B-3.控制优先程序”。 点击“梯形图编辑”…...
基于小程序老人监护管理系统源码数据库文档
摘 要 近年来,随着我国人口老龄化问题日益严重,独居和居住养老机构的的老年人数量越来越多。而随着老年人数量的逐步增长,随之而来的是日益突出的老年人问题,尤其是老年人的健康问题,尤其是老年人产生健康问题后&…...
