个人技术分享

说明

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

一:引入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

五:时区转化工具类

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()
		);
	}
}