springboot(3.2.5)初步集成MinIO(8.5.9)开发记录

springboot初步集成MinIO开发记录

  • 说明
  • 一:引入maven依赖
  • 二:手动注入minioClient
  • 三:创建service类
  • 四:测试打印连接信息
  • 五:时区转化工具类
  • 六:常用操作演示

说明

  • 这里只是作者开发的记录,已备将来完善和复习!内容很简单,大佬请路过。

一:引入maven依赖

  • 在项目pom中添加minio maven依赖
<dependency>
	<groupId>io.minio</groupId>
	<artifactId>minio</artifactId>
	<version>8.5.9</version>
</dependency>

二:手动注入minioClient

  • 由于minio官方没有提供spring-boot-starter-minio的启动类,所以,这里选择手动注入!
  • 在项目根目录下创建config软件包,创建config
    在这里插入图片描述
import io.minio.MinioClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {
    //链式编程 构建MinioClient对象
    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder()
                // .region("zh-east-8") 可选注意和minio的区域配置一致
                .endpoint("http://ip:9000")
                .credentials("minioadmin","minioadmin") // 默认 用户和秘密
                .build();
    }
}

三:创建service类

在这里插入图片描述

import io.minio.MinioClient;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

@Service
public class MinioService {
    @Resource
    private MinioClient minioClient;
    public void testMinioClient(){
        System.out.print(minioClient);
    }
}

四:测试打印连接信息

  • 在测试类中测试打印连接信息
@SpringBootTest
class MinioApplicationTests {
	@Resource
	private MinioService minioService;
	@Resource
	private MinioClient minioClient;
	@Test
	void test() {
		minioService.testMinioClient();
	}
}	
  • 测试结果
io.minio.MinioClient@7302ff13

五:时区转化工具类

  • 如果你困惑于文件最后修改时间和代码程序查询结果不一致,参看Minio(官方docker版)容器部署时区问题研究记录
    在这里插入图片描述
package com.yang.miniostudy01.utils;

import java.lang.annotation.Retention;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;

public class TimeConverter {

    // 使用自定义格式化模式
    private static final DateTimeFormatter isoFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .optionalStart()
            .appendOffsetId()
            .optionalEnd()
            .toFormatter();

    private static final DateTimeFormatter customFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendLiteral('Z') // 添加字面值 'Z' 表示时区偏移量
            .toFormatter();

    /**
     * 将UTC时间转换为指定时区的时间,格式保持ISO-8601 默认时区为东八区
     * @param utcTimeString UTC时间字符串(ISO-8601格式)
     * @return 指定时区的时间字符串(ISO-8601格式)
     */
    public static String convertUtcToLocal(String utcTimeString) {
        String zoneIdString="Asia/Shanghai";
        return convertUtcToLocal(utcTimeString,zoneIdString);
    }

    /**
     * 将UTC时间转换为指定时区的时间,格式保持ISO-8601
     * @param utcTimeString UTC时间字符串(ISO-8601格式)
     * @param zoneIdString 时区ID,如"Asia/Shanghai"
     * @return 指定时区的时间字符串(ISO-8601格式)
     */
    public static String convertUtcToLocal(String utcTimeString, String zoneIdString) {
        Instant utcTime = Instant.parse(utcTimeString);
        ZonedDateTime localTime = utcTime.atZone(ZoneId.of(zoneIdString));
        DateTimeFormatter formatter = customFormatter.withZone(ZoneId.of(zoneIdString));
        return formatter.format(localTime);
    }

    /**
     * 将本地时间转换为UTC时间
     * @param localTimeString 本地时间字符串(ISO-8601格式)
     * @param zoneIdString 时区ID,如"Asia/Shanghai"
     * @return UTC时间字符串(ISO-8601格式)
     */
    public static String convertLocalToUtc(String localTimeString) {
        String zoneIdString="Asia/Shanghai";
        return convertLocalToUtc(localTimeString,zoneIdString);
    }
    /**
     * 将本地时间转换为UTC时间
     * @param localTimeString 本地时间字符串(ISO-8601格式)
     * @param zoneIdString 时区ID,如"Asia/Shanghai"
     * @return UTC时间字符串(ISO-8601格式)
     */
    public static String convertLocalToUtc(String localTimeString, String zoneIdString) {
        ZonedDateTime localTime = ZonedDateTime.parse(localTimeString, customFormatter.withZone(ZoneId.of(zoneIdString)));
        Instant utcTime = localTime.toInstant();
        return isoFormatter.format(utcTime.atZone(ZoneId.of("UTC")));
    }
}

六:常用操作演示

package com.yang.miniostudy01;

import com.yang.miniostudy01.service.MinioService;
import com.yang.miniostudy01.utils.TimeConverter;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@SpringBootTest
class MinioApplicationTests {
	@Resource
	private MinioService minioService;
	@Resource
	private MinioClient minioClient;

	/**
	 * 判断桶是否存在
	 */
	@Test
	void testBucketExists(){
        try {
			boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket("test1").build());
			System.out.println("桶存在:"+exists);
		} catch (ErrorResponseException | XmlParserException | InsufficientDataException | InternalException |
                 ServerException | InvalidKeyException | InvalidResponseException | IOException |
                 NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
	/**
	 * 创建桶
	 */
	@Test
	void testBucketCreate() throws Exception {
		boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket("test02").build());
		if (!exists){
			minioClient.makeBucket(MakeBucketArgs.builder().bucket("test02").build());
		}
		System.out.println("bucket已存在,无需创建");
	}
	/**
	 * 获取桶列表
	 */
	@Test
	void testBucketList() throws Exception {
		List<Bucket> buckets = minioClient.listBuckets();
		buckets.forEach(bucket-> System.out.println(bucket.name()+"--"+bucket.creationDate()));
	}

	/**
	 * 删除桶
	 */
	@Test
	void testBucketRemove() throws Exception {
		minioClient.removeBucket(RemoveBucketArgs.builder().bucket("test02").build());
	}

	/**
	 * 上传文件
	 */

	@Test
	void testObjectPut() throws Exception{
		File file = new File("src/main/resources/picture/image.jpg");
		ObjectWriteResponse response = minioClient.putObject(
				PutObjectArgs.builder()
						.bucket("test02")
						.object("image.jpg")
						.stream(new FileInputStream(file),file.length(),-1)
						.build()
		);
		System.out.print(response);
	}

	/**
	 * 简单上传文件
	 */
	@Test
	void testObjectUpload() throws Exception {
		ObjectWriteResponse response = minioClient.uploadObject(
				UploadObjectArgs.builder()
						.bucket("test02")
						.object("image3.jpg")
						.filename("src/main/resources/picture/image.jpg")
						.build()
		);
		System.out.println(response);
	}

	/**
	 * 判断文件是否存在
	 */
	@Test
	void testObjectExists() throws Exception {
		StatObjectResponse response = minioClient.statObject(
				StatObjectArgs.builder()
						.bucket("test02")
						.object("image.jpg")
						.build()
		);
		System.out.println("修改前文件信息:"+response);

		String localLastModifiedTime = TimeConverter.convertUtcToLocal(response.lastModified().toString());
		ZonedDateTime localLastModified = ZonedDateTime.parse(localLastModifiedTime);
		//通过反射 修改文件信息 不影响minio存储的文件信息
		try {
			Field lastModifiedField = response.getClass().getDeclaredField("lastModified");
			lastModifiedField.setAccessible(true);
			lastModifiedField.set(response, localLastModified);
		} catch (NoSuchFieldException | IllegalAccessException e) {
			e.printStackTrace();
		}

		System.out.println("修改后文件信息:"+response);
	}

	/**
	 * 获取文件访问路径
	 */
	@Test
	void testObjectUrl() throws Exception {
		String objectUrl = minioClient.getPresignedObjectUrl(
				GetPresignedObjectUrlArgs.builder()
						.bucket("test02")
						.object("image.jpg")
						.method(Method.GET)
						.expiry(5, TimeUnit.MINUTES)
						.build()
		);
		System.out.println(objectUrl);
	}

	/**
	 * 配置桶自定义权限
	 */
	@Test
	void testBucketCreateWithPrivilege() throws Exception {
		String bucketName="test02";
		boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
		if (!exists){
			minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
		}else{
			System.out.println("bucket已存在,无需创建");
		}

		// 定义存储桶的访问策略为公开
		// 定义公共访问策略
		String policyJson = "{\n" +
				"    \"Version\": \"2012-10-17\",\n" +
				"    \"Statement\": [\n" +
				"        {\n" +
				"            \"Sid\": \"PublicRead\",\n" +
				"            \"Effect\": \"Allow\",\n" +
				"            \"Principal\": \"*\",\n" +
				"            \"Action\": \"s3:GetObject\",\n" +
				"            \"Resource\": \"arn:aws:s3:::" + bucketName + "/*\"\n" +
				"        }\n" +
				"    ]\n" +
				"}";

		minioClient.setBucketPolicy(
				SetBucketPolicyArgs.builder()
						.bucket(bucketName)
						.config(policyJson)
						.build()
		);
	}

	/**
	 * 文件下载
	 */
	@Test
	public void testObjectDownload() throws Exception {
		GetObjectResponse objectFile = minioClient.getObject(
				GetObjectArgs.builder()
						.bucket("test02")
						.object("image.jpg")
						.build()
		);
		System.out.println(objectFile.transferTo(new FileOutputStream("src/main/resources/picture/test.jpg")));
	}

	/**
	 * 获取桶内文件信息
	 */
	@Test
	public void testObjectList(){
		Iterable<Result<Item>> results = minioClient.listObjects(
				ListObjectsArgs.builder()
						.bucket("test02")
						.build()
		);
		results.forEach((itemResult)->{
            try {
				Item item = itemResult.get();
				System.out.println(item.objectName()+" \t"+item.lastModified()+"\t"+item.size());
            } catch (ErrorResponseException | XmlParserException | ServerException | NoSuchAlgorithmException |
                     InvalidResponseException | InsufficientDataException | InvalidKeyException | IOException |
                     InternalException e) {
                throw new RuntimeException(e);
            }
        });
	}

	/**
	 * 删除文件
	 */
	@Test
	public void testRemoveObject() throws Exception {
		minioClient.removeObject(
				RemoveObjectArgs.builder()
						.bucket("test02")
						.object("5g3pl8.jpg")
						.build()
		);
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

理解导数(x^n求导后nx^n-1)

以下都是为了方便理解 微小量是 t M(x)是一个函数 M 在 x 处的斜率 M 在 x 处的导数 垂直距离 平移距离 M ( x t ) − M ( x ) ( x t ) − x M在x处的斜率 M在x处的导数 \dfrac{垂直距离}{平移距离} \dfrac{M\left( xt\right) -M\left( x\right) }{(x t) -x} M在x处的斜…

数组二叉树-华为OD

系列文章目录 文章目录 系列文章目录前言一、题目描述二、输入描述三、输出描述四、java代码五、测试用例 前言 本人最近再练习算法&#xff0c;所以会发布一些解题思路&#xff0c;希望大家多指教 一、题目描述 二叉树也可以用数组来存储&#xff0c;给定一个数组&#xff…

Qt之常用控件一

Widget常见属性及其作用 属性作用enabled 设置控件是否可使⽤. true 表⽰可⽤, false 表⽰禁⽤ geometry 位置和尺⼨. 包含 x, y, width, height 四个部分. 其中坐标是以⽗元素为参考进⾏设置的. windowTitle 设置 widget 标题 windowIcon 设置 widget 图标 windowOpa…

安装SQL Server详细教程_sql server安装教程

一&#xff0c;SQL Server数据库安装 1.首先&#xff0c;下载安装程序 &#xff08;1&#xff09;从网盘下载安装exe 点击此处直接下载 &#xff08;2&#xff09;从官网下载安装exe文件 在官网选择Developer进行下载 2.开始安装 双击安装程序&#xff0c;开始安装 这里直…

数据的均匀化分割算法(网格划分法、四叉树法(含C++代码))

数据的均匀化分割主要是指在分割过程中尽可能均匀地将数据点分布在各个子区域中&#xff0c;以保持数据分布的平衡和优化数据结构的性能。以下是几种可以实现数据均匀化分割的方法&#xff1a; 一. 网格划分法 1. 基本概念 虽然传统的网格划分法不是动态调整的&#xff0c;但通…

2024年电工杯数学建模A题思路 中国电机工程学会杯建模思路分析

文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

【高校科研前沿】北师大陈晋教授团队在遥感顶刊发表最新成果:ClearSCD模型:在高空间分辨率遥感影像中综合利用语义和变化关系进行语义变化检测

01文章简介 论文名称&#xff1a;The ClearSCD model: Comprehensively leveraging semantics and change relationships for semantic change detection in high spatial resolution remote sensing imagery&#xff08;ClearSCD模型&#xff1a;在高空间分辨率遥感影像中综合…

在Spring Boot应用安装SSL证书

目录 前提条件 步骤一&#xff1a;下载SSL证书 步骤二&#xff1a;在Spring Boot安装SSL证书 步骤三&#xff1a;验证SSL证书是否安装成功 前提条件 已通过数字证书管理服务控制台签发证书SSL证书绑定的域名已完成DNS解析&#xff0c;即您的域名与主机IP地址相互映射已在W…

[Markdown]是时候该学学使用markdown写文章了

&#x1f495;&#x1f495;&#x1f495;欢迎各位来到我的博客&#xff0c;今天我们的主题是markdown&#xff0c;你将在这里学习到最全的markdown知识&#x1f495;&#x1f495;&#x1f495; 你还在使用富文本编辑器写文档或文章吗&#xff1f; 你还在用word一点一点地进行…

网络匿名--不只是TOR

今天&#xff0c;我们将讨论互联网匿名和隐私&#xff1a; 如何隐藏你的真实身份。 什么是 TOR 。 如何以完全匿名的方式执行黑客任务。 如何使用proxy chain。 如何让我们的匿名性领先一步。 如何使用特定的操作系统保持匿名。 结论&#xff0c;如何实现互联网匿名和隐…

2024高校网络安全管理运维赛wp

文章目录 misc签到钓鱼邮件识别easyshellSecretDBGatewayzipApachef for r webphpsqlMessy Mongo misc 签到 钓鱼邮件识别 两部分解base64&#xff0c;各一个flag 后面没有什么地方有有用信息了&#xff0c;根据题目钓鱼邮件&#xff0c;可能第三段flag就跟DMARC、DKIM 和 SP…

ppt通过修改幻灯片母版修改页脚

修改幻灯片母版 幻灯片母版就可以了&#xff0c;就可以修改页脚

如何打破数据管理僵局,释放数据资产价值?[AMT企源案例]

引言 数据是企业信息运作的核心和基础&#xff0c;是影响企业决策的关键要素&#xff0c;而主数据是数据中的最基础和公共的部分。面临长期以来的数据治理缺失导致的杂论局面&#xff0c;如何有条不紊推进主数据管理&#xff0c;让数据资产“活”起来&#xff1f;S集团的做法非…

Linux线程(二)线程互斥

目录 一、为什么需要线程互斥 二、线程互斥的必要性 三、票务问题举例&#xff08;多个线程并发的操作共享变量引发问题&#xff09; 四、互斥锁的用法 1.互斥锁的原理 2、互斥锁的使用 1、初始化互斥锁 2、加锁和解锁 3、销毁互斥锁&#xff08;动态分配时需要&#…

PostgreSQL的学习心得和知识总结(一百四十三)|深入理解PostgreSQL数据库之Support event trigger for logoff

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

Stable Diffusion教程|图生图原理和实战

Stable Diffusion凭借其卓越的图生图功能&#xff0c;极大地提升了图像生成的可控性与输出品质&#xff0c;赋予用户前所未有的个性化创作风格表达能力。这一革新特性使得Stable Diffusion不仅能精准地捕捉用户的艺术愿景&#xff0c;更能以数字化手段孕育出新颖且极具创意的画…

论文 学习 Transformer : Attention Is All You Need

目录 概述&#xff1a; 对摘要的理解&#xff1a; 框架解析 按比例缩放的点积注意力 多头注意力机制 前馈神经网络与位置编码 概述&#xff1a; transformer 是一个encoder ——decoder 结构的用于处理序列到序列转换任务的框架&#xff0c;是第一个完全依赖自注意力机制…

写了 1000 条 Prompt 之后,我总结出了这 9 个框架【建议收藏】

如果你对于写 Prompt 有点无从下手&#xff0c;那么&#xff0c;本文将为你带来 9 个快速编写 Prompt 的框架&#xff0c;你可以根据自己的需求&#xff0c;选择任意一个框架&#xff0c;填入指定的内容&#xff0c;即可以得到一段高效的 Prompt&#xff0c;让 LLM 给你准确满意…

再谈毕业论文设计投机取巧之IVR自动语音服务系统设计(信息与通信工程A+其实不难)

目录 举个IVR例子格局打开&#xff0c;万物皆能IVR IVR系统其实可盐可甜。还能可圈可点。 戎马一生&#xff0c;归来依然IVR。 举个IVR例子 以下是IVR系统的一个例子。 当您拨打电话进入IVR系统。 首先检验是否为工作时间。 如是&#xff0c;您将被送入ivr-lang阶段&#xff0…