使用docker创建minio镜像并上传文件,提供demo

使用docker创建minio镜像并上传文件,提供demo

  • 1. 整体描述
  • 2. 环境搭建
    • 2.1 windows环境搭建
    • 2.2 docker部署
  • 3. spring集成
    • 3.1 添加依赖
    • 3.2 配置文件
    • 3.3 创建config类
    • 3.4 创建minio操作类
    • 3.5 创建启动类
    • 3.6 测试controller
  • 4. 测试操作
    • 4.1 demo运行
    • 4.2 页面查看
    • 4.3 上传文件
    • 4.4 预览/下载文件
  • 5. demo下载
  • 6. 总结

1. 整体描述

MinIO是一个对象存储解决方案,它提供了一个Amazon Web Services S3兼容的API,并支持所有S3的核心特性。MinIO可以部署在任何地方——公共云或私有云、裸机基础设施、编排环境和边缘基础设施。

本文档介绍MinIO最新稳定版本RELEASE.2023-09-04T19-57-37Z在Windows平台上部署MinIO的操作、管理和开发。

上面是官网介绍,用有道翻译的,官网地址: 链接。

2. 环境搭建

使用docker搭建minio环境,可以直接用官网下载minio镜像,我们先用windows环境搭建一下。

2.1 windows环境搭建

在官网下载页面,选择windows,下载的是一个minion.exe文件。我放在了d:/minio目录下,在此再创建一个data文件夹,用来储存minio上传的文件。
然后在命令行执行如下指令启动minio:

setx MINIO_ROOT_USER minioadmin
setx MINIO_ROOT_PASSWORD minioadmin
D:\minio\minio.exe server D:\minio\data\ --console-address ":9001"

看到如下就说明启动成功了:
windowsminio启动
然后通过浏览器访问:
http://localhost:9001/
进入如下登录页面:
默认用户名和密码都是minioadmin
minio登录页面

2.2 docker部署

使用docker部署就更简单了,首先拉取官方镜像:

docker pull minio/minio

拉取成功之后,执行创建和启动容器:

docker run -p 9000:9000 -p 9001:9001 minio/minio server /data --console-address ":9001"

看到如下就说明启动成功:
docker启动minio
同样通过浏览器访问:
http://localhost:9001/
进入如下登录页面:
默认用户名和密码都是minioadmin

3. spring集成

通过springboot框架集成minio,实现上传文件的目的。

3.1 添加依赖

首先创建一个springboot工程,添加如下依赖:

<!-- lombok 自动生成方法--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency><!--io常用工具类 --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.5</version></dependency><!--常用工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><!-- minio--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.6</version></dependency>

3.2 配置文件

在springboot的yml配置文件中添加minio环境的配置:

#minio相关配置
minio:endpoint: http://127.0.0.1:9000accessKey: minioadminsecretKey: minioadmin

3.3 创建config类

package com.thcb.miniodemo.config;import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;/*** MinioUtil** @author thcb* @date 2023-09-05*/
@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();}}

3.4 创建minio操作类

minio操作类,用来写minio基础方法

package com.thcb.miniodemo.minio;import com.thcb.miniodemo.utils.*;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;/*** MinioUtil** @author thcb* @date 2023-09-05*/
@Component
@Slf4j
@RequiredArgsConstructor
public class MinioUtil {private final MinioClient minioClient;/*** 两票数据桶*/public static String TEST_BUCKET = "test";private static String POLICY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::%s\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::%s/*\"]}]}";public void initMinIo() {log.warn("start initMinIo.");if (!bucketExists(TEST_BUCKET)) {log.warn("start makeBucket {}.", TEST_BUCKET);makeBucket(TEST_BUCKET);log.warn("finish makeBucket {}.", TEST_BUCKET);}try {log.warn("start setBucketPolicy {}.", TEST_BUCKET);minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(TEST_BUCKET).config(String.format(POLICY, TEST_BUCKET, TEST_BUCKET)).build());log.warn("finish setBucketPolicy {}.", TEST_BUCKET);} catch (Exception e) {log.error("setBucketPolicy from minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));}}/*** 查看存储bucket是否存在** @return boolean*/public Boolean bucketExists(String bucketName) {Boolean found;try {found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());} catch (Exception e) {log.error("bucketExists from minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));return false;}return found;}/*** 创建存储bucket** @return Boolean*/public synchronized Boolean makeBucket(String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {log.error("makeBucket from minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));return false;}return true;}/*** 删除存储bucket** @return Boolean*/public synchronized Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {log.error("removeBucket from minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));return false;}return true;}/*** 获取全部bucket*/public List<Bucket> getAllBuckets() {try {List<Bucket> buckets = minioClient.listBuckets();return buckets;} catch (Exception e) {log.error("getAllBuckets from minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));}return null;}/*** 文件上传** @param file       文件* @param bucketName 桶名称* @return Boolean*/public synchronized String upload2Bucket(MultipartFile file, String bucketName) {return String.format("/%s/%s", bucketName, upload(file, bucketName));}/*** 文件上传** @param file       文件* @param bucketName 桶名称* @return Boolean*/public synchronized String upload(MultipartFile file, String bucketName) {String originalFilename = file.getOriginalFilename();if (StringUtils.isBlank(originalFilename)) {throw new CustomException("文件格式错误");}String fileName = UUIDUtil.UUID() + originalFilename.substring(originalFilename.lastIndexOf("."));String objectName = DateUtils.dateTimeNow(DateUtils.YYYYMMDD) + "/" + fileName;try {PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();//文件名称相同会覆盖minioClient.putObject(objectArgs);} catch (Exception e) {log.error("upload file to minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));return null;}return objectName;}/*** 文件上传** @param file 文件* @return Boolean*/public synchronized String upload(MultipartFile file) {return upload(file, TEST_BUCKET);}/*** 预览** @param fileName* @return*/public String preview(String fileName) {return preview(fileName, TEST_BUCKET);}/*** 预览** @param fileName* @param bucketName 桶名称* @return*/public String preview(String fileName, String bucketName) {// 查看文件地址GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build();try {String url = minioClient.getPresignedObjectUrl(build);return url;} catch (Exception e) {log.error("preview file to minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));}return null;}/*** 文件下载** @param fileName         文件名称* @param originalFileName 原文件名称* @param res              response* @return Boolean*/public void download(String fileName, String originalFileName, HttpServletRequest req, HttpServletResponse res) {download(fileName, TEST_BUCKET, req, res);}/*** 文件下载** @param fileName         文件名称* @param bucketName       桶名称* @param originalFileName 原文件名称* @param res              response* @return Boolean*/public void download(String fileName, String bucketName, String originalFileName, HttpServletRequest req, HttpServletResponse res) {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).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");String type = req.getHeader("User-Agent").toLowerCase();String firefox = "firefox", chrome = "chrome";String encodedFileName;if (type.indexOf(firefox) > 0 || type.indexOf(chrome) > 0) {encodedFileName = new String(originalFileName.getBytes(StandardCharsets.UTF_8), "iso8859-1");} else {encodedFileName = URLEncoder.encode(originalFileName, StandardCharsets.UTF_8.name());}// 设置强制下载不打开// res.setContentType("application/force-download");// res.setContentType("application/octet-stream");res.setContentType(FileDownloadUtils.getFileContentType(fileName));res.addHeader("Content-Disposition", "attachment;fileName=" + encodedFileName + ";filename*=utf-8''" + encodedFileName);res.addHeader("Content-Length", bytes.length + "");try (ServletOutputStream stream = res.getOutputStream()) {stream.write(bytes);stream.flush();}}res.flushBuffer();} catch (Exception e) {log.error("download file from minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));}}/*** 删除** @param fileName* @return* @throws Exception*/public boolean remove(String fileName) {return remove(fileName, TEST_BUCKET);}/*** 删除** @param fileName* @return* @throws Exception*/public synchronized boolean remove(String fileName, String bucketName) {try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());} catch (Exception e) {log.error("remove file from minio occur exception. e={}", ExceptionUtil.getExceptionMessage(e));return false;}return true;}}

3.5 创建启动类

在springboot启动成功后连接minio

package com.thcb.miniodemo.listener;import com.thcb.miniodemo.minio.MinioUtil;
import com.thcb.miniodemo.utils.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;/*** ApplicationReadyListener** @author thcb* @date 2023-09-05*/
@Component
public class ApplicationReadyListener implements ApplicationListener<ApplicationReadyEvent> {private static final Logger log = LoggerFactory.getLogger(ApplicationReadyListener.class);@Autowiredprivate MinioUtil minioUtil;@Overridepublic void onApplicationEvent(ApplicationReadyEvent event) {try {doPostConstruct();} catch (Exception e) {log.error("e={}", ExceptionUtil.getExceptionMessage(e));}}private void doPostConstruct() {log.info("initMinIo");initMinIo();}/*** 初始化minio桶文件*/private void initMinIo() {minioUtil.initMinIo();}
}

3.6 测试controller

写一个测试的controller,测试minio相关功能

package com.thcb.miniodemo.controller;import com.thcb.miniodemo.minio.MinioUtil;
import com.thcb.miniodemo.utils.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;/*** TestController** @author thcb* @date 2023-09-05*/
@RestController
@RequestMapping("/TestController")
public class TestController {private static final Logger log = LoggerFactory.getLogger(TestController.class);@Autowiredprivate MinioUtil minioUtil;@RequestMapping("/test")@ResponseBodypublic String test() {return "test success";}@PostMapping("/uploadFile")public AjaxResult uploadFile(MultipartFile file) throws Exception {try {String pathUrl = minioUtil.upload2Bucket(file, MinioUtil.TEST_BUCKET);return AjaxResult.success(pathUrl);} catch (Exception e) {return AjaxResult.error(e.toString());}}
}

4. 测试操作

4.1 demo运行

运行工程,如下log说明连接成功:
miniodemo运行

4.2 页面查看

运行完成,在页面应该能看到我们创建的桶:
桶

4.3 上传文件

使用postman调用我们写的测试接口,上传一个文件到minio
postman调用
上传成功,在页面上也可以看到这个文件:
文件查看

4.4 预览/下载文件

如果上传的是图片,通过返回的url,浏览器可以直接访问预览,如果是其他类型的文件,是可以通过这个返回的url进行下载的:
http://localhost:9000/test/20230908/2b31664c4a004a5cb4b2934ebf5300cd.jpg

5. demo下载

minio的demo已经上传到csdn,需要的可以自行下载,在本文基本也把主要的核心代码都贴出来了,这个demo使用的是springboot框架,加了一些工具类,可以直接拿来用,或者新工程改个名字就能用了。demo结构截图:
demo结构
demo工程地址:demo下载地址,传到了gitcode上,应该是csdn弄的一个代码仓库,和git差不多。

6. 总结

minio还是很方便的,从部署到使用,都可以非常快速的搭建,而且比较稳定。

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

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

相关文章

debian下快速搭建php环境并验证

目录 安装 验证 安装 更新软件包&#xff1a; sudo apt update 升级软件包&#xff1a; sudo apt upgrade 安装 sudo apt-get install php7.3 php7.3-fpm php7.3-mysql php7.3-redis php7.3-cli php7.3-curl php7.3-json php7.3-mbstring php7.3-opcache php7.3-readli…

【云计算】虚拟私有网络 VPC

虚拟私有网络 VPC 1.VPC 简介1.1 VPC 相关基本概念1.2 其他相关基本概念 2.VPC 通信场景2.1 VPC 内部互通2.2 VPC 间互通2.2.1 对等连接2.2.2 Transit Gateway 或者云联网 2.3 访问 Internet2.3.1 Internet 网关2.3.2 NAT 网关 2.4 访问本地网络2.4.1 VPN 连接2.4.2 专线接入2.…

pytorch生成CAM热力图-单张图像

利用ImageNet预训练模型生成CAM热力图-单张图像 一、环境搭建二、主要代码三、结果展示 代码和图片等资源均来源于哔哩哔哩up主&#xff1a;同济子豪兄 讲解视频&#xff1a;CAM可解释性分析-算法讲解 一、环境搭建 1&#xff0c;安装所需的包 pip install numpy pandas mat…

原生微信小程序中进行 API 请求

原生微信小程序中进行 API 请求 当在原生微信小程序中进行 API 请求时&#xff0c;封装请求可以提高代码的可维护性和可扩展性。在本篇博客中&#xff0c;我们将一步步介绍如何进一步封装请求&#xff0c;并添加请求超时、拦截器和请求取消功能。 第一步&#xff1a;基本请求封…

混淆矩阵细致理解

1、什么是混淆矩阵 混淆矩阵&#xff08;Confusion Matrix&#xff09;是深度学习和机器学习领域中的一个重要工具&#xff0c;用于评估分类模型的性能。它提供了一个清晰的视觉方式来展示模型的预测结果与真实标签之间的关系&#xff0c;尤其在分类任务中&#xff0c;帮助我们…

【Unity基础】2.网格材质贴图与资源打包

【Unity基础】2.网格材质贴图与资源打包 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity基础系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;网格材质纹理 第一次接触3D物体的话&#xff0c;会觉得好神奇啊&#xff0c;这个物体究竟是由什么组…

[python 刷题] 217 Contains Duplicate

[python 刷题] 217 Contains Duplicate 题目&#xff1a; Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct. 一道非常简单的入门题&#xff0c;新建一个 set 去保存所有的值&…

基于安卓Java试题库在线考试系统uniapp 微信小程序

本文首先分析了题库app应用程序的需求&#xff0c;从系统开发环境、系统目标、设计流程、功能设计等几个方面对系统进行了系统设计。开发出本题库app&#xff0c;主要实现了学生、教师、测试卷、试题、考试等。总体设计主要包括系统功能设计、该系统里充分综合应用Mysql数据库、…

Ae 效果:CC Particle Systems II

模拟/CC Particle Systems II Simulation/CC Particle Systems II CC Particle Systems II&#xff08;CC 粒子系统 II&#xff09;可用于生成和模拟各种类型的粒子系统&#xff0c;包括火焰、雨、雪、爆炸、烟雾等等。 与 CC Particle World 效果相比有许多类似的属性。最大的…

前端该了解的网络知识

网络 前端开发需要了解的网络知识 URL URL(uniform resource locator,统一资源定位符)用于定位网络服务. URL是一个固定格式的字符串 它表达了: 从网络中哪台计算机(domain)中的哪个服务(port),获取服务器上资源的路径(path),以及要用什么样的协议通信(schema). 注意: 当…

C# wpf 实现桌面放大镜

文章目录 前言一、如何实现&#xff1f;1、制作无边框窗口2、Viewbox放大3、截屏显示&#xff08;1&#xff09;、截屏&#xff08;2&#xff09;、转BitmapSource&#xff08;3&#xff09;、显示 4、定时截屏 二、完整代码三、效果预览总结 前言 做桌面截屏功能时需要放大镜…

MySQL 导出和导入数据

文章目录 一&#xff0c;导出数据&#xff08;一&#xff09;使用SELECT ... INTO OUTFILE语句导出数据&#xff08;二&#xff09;使用mysqldump工具导出数据&#xff08;三&#xff09;使用SELECT ... INTO DUMPFILE语句导出数据 二&#xff0c;导入数据&#xff08;一&#…

卫星物联网生态建设全面加速,如何抓住机遇?

当前&#xff0c;卫星通信无疑是行业最热门的话题之一。近期发布的华为Mate 60 Pro“向上捅破天”技术再次升级&#xff0c;成为全球首款支持卫星通话的大众智能手机&#xff0c;支持拨打和接听卫星电话&#xff0c;还可自由编辑卫星消息。 据悉&#xff0c;华为手机的卫星通话…

什么是数据压缩?解释数据压缩的原理和不同的压缩算法

1、什么是数据压缩&#xff1f;解释数据压缩的原理和不同的压缩算法。 数据压缩是一种通过减少数据的冗余来减小数据大小的计算机技术。它的原理是在保持数据完整性或可识别性的前提下&#xff0c;将原始数据压缩为较小的格式&#xff0c;以便于存储、传输和打印。 不同的压缩…

【Unity每日一记】资源加载相关和检测相关

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

Python -【多态,抽象类,鸭子类型】的区别及使用

一. 前言 Python中的抽象类、多态和鸭子类型都是实现代码灵活性的机制&#xff0c;但它们之间还是有一些区别的。 二. 三者的区别 抽象类&#xff1a; 要求子类必须实现某些方法&#xff0c;从而规范了子类的实现方式。多态&#xff1a; 同一个方法可以针对不同类型的对象进…

【计算机网络】Tcp详解

文章目录 前言Tcp协议段格式TCP的可靠性面向字节流应答机制超时重传流量控制滑动窗口&#xff08;重要&#xff09;拥塞控制延迟应答捎带应答标志位具体标志位三次握手四次挥手粘包问题TCP异常情况listen的第二个参数 前言 前面我们学习了传输层协议Udp&#xff0c;今天我们一…

invalid use of incomplete type ‘class Ui::xxx‘

MainWindow 引用自定义窗口报错&#xff1a;invalid use of incomplete type class Ui::xxx mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include "form.h" form.cpp #include "form.h" #include "…

使用FFmpeg+ubuntu系统转化flac无损音频为mp3

功能需求如上题,我们来具体的操作一下: 1.先在ubuntu上面安装FFmpeg:sudo apt install ffmpeg 2.进入有flac音频文件的目录使用下述命令: ffmpeg -i test.FLAC -c:a libmp3lame -q:a 2 output.mp3 3.如果没有什么意外的话,你就能看到你的文件夹里面已经有转化好的mp3文件了 批…

ubuntu中如何用docker下载华为opengauss数据库(超简单)

ubuntu中如何下载华为opengauss数据库 前言一、安装docker1.方法一&#xff1a;2.方法二 二、拉取openguass镜像三、创建容器四、连接数据库 ,切换到omm用户 &#xff0c;用gsql连接到数据库五.最后用DateGrip远程连接测试(1&#xff09;选择数据源(2&#xff09;查看虚拟机ip地…