当前位置: 首页 > news >正文

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内核&#xff0c;必须是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多进程之后&#xff0c;我们可以继续探索multiprocessing包中更加高级的工具。这些工具可以让我们更加便利地实现多进程。 进程池 进程池 (Process Pool)可以创建多个进程。这些进程就像是随时待命的士兵&#xff0c;准备执行任务(程序)。一个进程池中可以容…...

Boris FX Mocha Pro 2023:Mac/win全能影像处理神器

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

elementUI 特定分辨率(如1920*1080)下el-row未超出一行却换行

在1920*1080分辨率下&#xff0c; el-col 内容未超出 el-col 宽度&#xff0c;el-col 不足以占据一行&#xff0c;el-row 却自动换行了&#xff08;其他分辨率没有这个问题&#xff09;。 截图&#xff1a; 排查&#xff1a; el-col 内容没有溢出&#xff1b;没有多余的 pad…...

mac电脑视频处理推荐:达芬奇DaVinci Resolve Studio 18 中文最新

DaVinci Resolve Studio 18是一款专业的视频编辑、调色和后期制作软件&#xff0c;由Blackmagic Design开发。它被广泛应用于电影、电视和广告等行业&#xff0c;提供了全面的工具和功能&#xff0c;使用户能够进行高质量的影片制作和后期处理。 以下是DaVinci Resolve Studio…...

OKLink携手CertiK在港举办Web3生态安全主题论坛

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

王道p40 1.设计一个递归算法,删除不带头结点的单链表L中的所有值为x的结点(c语言代码实现)图解递归

视频讲解(献丑了)&#xff1a;p40 第1题 王道数据结构课后代码题c语言代码实现_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Xa4y1Q7ui/?spm_id_from333.999.0.0 首先它是一个不带头结点的单链表 我们就得特殊处理 我们先让*LNULL&#xff1b; 然后为s开辟一个新…...

深入浅出排序算法之希尔排序

目录 1. 原理 2. 代码实现 3. 性能分析 1. 原理 希尔排序法又称缩小增量法。希尔排序法的基本思想是&#xff1a;先选定一个整数&#xff0c;把待排序文件中所有记录分成个组&#xff0c;所有距离为的记录分在同一组内&#xff0c;并对每一组内的记录进行排序。然后&#xf…...

close excel by keyword 根据关键字关闭 excel 窗口 xlwings 方式实现

根据标题关键字关闭 workbook&#xff0c;如果没有打开的 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的紧耦合&#xff0c;采用一个因子图对位姿进行优化&#xff0c;包括IMU因子&#xff0c;激光里程计因子&#xff0c…...

vscode 提升小程序开发效率的必备插件与工具

1&#xff0c;微信小程序开发助手&#xff08;WeChat Snippet&#xff09;&#xff1a;提供了小程序代码片段、模板和快速生成页面的功能&#xff0c;加快了开发速度。 2&#xff0c;小程序助手&#xff08;Minapp&#xff09;&#xff1a;提供了小程序项目创建、编译、预览和…...

第五章单元测试

一、学习目的与要求 本章对单元测试进行了详细的介绍。通过本章的学习&#xff0c;应掌握单元测试的概念&#xff0c;了解单元测试的误区&#xff0c;掌握单元测试的策略、分析方法和用例设计方法。 二、考核知识点与考核目标 &#xff08;一&#xff09;单元测试的概念&#…...

【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间的通信与安全)

前言 之前的提到了交换机的概念和实验。不过交换机的一些功能还没有说完&#xff0c;我们的实验也仅仅是阻止相同地址段的IP地址互通&#xff0c;也没有用到子接口和路由器。显然&#xff0c;那样的配置过于简单。 端口安全 Port Security&#xff08;端口安全&#xff09;的功…...

Linux shell编程学习笔记16:bash中的关联数组

上一节我们探讨了普通的数组&#xff0c;即使用数字下标来索引数组中不同的元素的数组&#xff0c;也可以称之为索引数组。 相比纯粹的数字&#xff0c;字符串不仅能表明含义&#xff0c;也更便于记忆使用&#xff0c;于是就有了关联数组。 一、关联数组概述 bash 从4.0开始支…...

浏览器是怎么执行JS的?——消息队列与事件循环

看完渡一的课后&#xff0c;感觉这块内容确实非常重要&#xff0c;写 JS 的连 JS 的执行原理都不知道可不行。 事件循环 在写 JS 的时候&#xff0c;你有没有想过 JS 是按照什么顺序执行的&#xff1f;浏览器是怎么执行 JS 代码的&#xff1f;为什么有时候代码没有按照我们认为…...

IMU预积分的过程详解

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

对比直接使用厂商 API 体验 Taotoken 在模型切换上的便利性

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 对比直接使用厂商 API 体验 Taotoken 在模型切换上的便利性 在个人开发项目中接入大模型时&#xff0c;开发者通常面临一个选择&am…...

深度解析Scarab:空洞骑士模组管理器的专业实现与架构设计

深度解析Scarab&#xff1a;空洞骑士模组管理器的专业实现与架构设计 【免费下载链接】Scarab An installer for Hollow Knight mods written with Avalonia. 项目地址: https://gitcode.com/gh_mirrors/sc/Scarab 空洞骑士模组管理器Scarab为玩家提供了高效、专业的模组…...

终极FGO自动化助手:告别枯燥刷本,每天节省3小时游戏时间

终极FGO自动化助手&#xff1a;告别枯燥刷本&#xff0c;每天节省3小时游戏时间 【免费下载链接】FGA Auto-battle app for F/GO Android 项目地址: https://gitcode.com/gh_mirrors/fg/FGA Fate/Grand Automata&#xff08;简称FGA&#xff09;是一款专为Fate/Grand Or…...

小红书无水印下载工具XHS-Downloader:3种使用模式全解析

小红书无水印下载工具XHS-Downloader&#xff1a;3种使用模式全解析 【免费下载链接】XHS-Downloader 小红书&#xff08;XiaoHongShu、RedNote&#xff09;链接提取/作品采集工具&#xff1a;提取账号发布、收藏、点赞、专辑作品链接&#xff1b;提取搜索结果作品、用户链接&a…...

Qdrant Python客户端全解析:从向量数据库连接到AI应用开发实战

1. 项目概述&#xff1a;从向量数据库到客户端&#xff0c;现代AI应用落地的关键拼图如果你最近在折腾大语言模型应用&#xff0c;或者想给自己的产品加上一个“智能大脑”&#xff0c;那你大概率已经听过“向量数据库”这个词了。简单来说&#xff0c;它就像一个专门为AI模型设…...

Go语言静态站点生成器Zeuxis:极简架构与高性能构建实践

1. 项目概述&#xff1a;一个轻量级、高性能的静态站点生成器最近在折腾个人博客和文档站点&#xff0c;发现市面上的静态站点生成器虽然多&#xff0c;但要么配置复杂、学习曲线陡峭&#xff0c;要么过于臃肿&#xff0c;启动和构建速度慢得让人抓狂。直到我遇到了bnomei/zeux…...

构建个人代码仓库:提升开发效率的实践指南

1. 项目概述&#xff1a;一个面向21世纪开发者的代码仓库最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“21st-dev/1code”。光看这个名字&#xff0c;你可能觉得有点抽象&#xff0c;但点进去之后&#xff0c;我发现它其实是一个挺有想法的代码仓库。这个项目没有复杂的…...

Claude-Code-KnowCraft:轻量级代码知识库构建与智能问答实践

1. 项目概述与核心价值最近在跟几个做AI应用开发的朋友聊天&#xff0c;大家普遍有个痛点&#xff1a;想把Claude这类大语言模型&#xff08;LLM&#xff09;的能力深度集成到自己的代码库分析工具里&#xff0c;但发现现有的方案要么太重&#xff0c;要么太浅。太重的是指那些…...

Grad-CAM实战:用热力图透视神经网络的决策焦点

1. Grad-CAM技术初探&#xff1a;为什么我们需要热力图&#xff1f; 当你训练了一个图像分类模型&#xff0c;准确率高达95%&#xff0c;但你真的了解它是如何做出判断的吗&#xff1f;我曾在项目中遇到过这样的尴尬&#xff1a;模型把一只坐在草地上的哈士奇误判为"狼&qu…...

基于MCP与Apify构建AI驱动的投资另类数据研究工具

1. 项目概述&#xff1a;当投资研究遇上AI代理如果你是一名量化研究员、对冲基金分析师&#xff0c;或者只是一个对金融市场充满好奇、希望用数据驱动决策的独立投资者&#xff0c;那么你肯定对“另类数据”这个词不陌生。传统的财报、股价、宏观经济指标&#xff0c;这些“传统…...