Переглянути джерело

:sparkles: add minioTemplate, support minio

冷冷 6 роки тому
батько
коміт
d76777fdf7

+ 24 - 0
pigx-common/pigx-common-minio/pom.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx-common</artifactId>
+		<version>2.0.0</version>
+	</parent>
+
+	<artifactId>pigx-common-minio</artifactId>
+	<packaging>jar</packaging>
+
+	<description>pigx 文件系统依赖</description>
+
+	<dependencies>
+		<dependency>
+			<groupId>io.minio</groupId>
+			<artifactId>minio</artifactId>
+			<version>${minio.version}</version>
+		</dependency>
+	</dependencies>
+</project>

+ 48 - 0
pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/MinioAutoConfiguration.java

@@ -0,0 +1,48 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.common.minio;
+
+import com.pig4cloud.common.minio.service.MinioTemplate;
+import lombok.AllArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * minio 自动配置类
+ *
+ * @author lengleng
+ */
+@AllArgsConstructor
+@EnableConfigurationProperties({MinioProperties.class})
+public class MinioAutoConfiguration {
+	private final MinioProperties properties;
+
+	@Bean
+	@ConditionalOnMissingBean(MinioTemplate.class)
+	@ConditionalOnProperty(name = "minio.url")
+	MinioTemplate template() {
+		return new MinioTemplate(
+				properties.getUrl(),
+				properties.getAccessKey(),
+				properties.getSecretKey()
+		);
+	}
+
+}

+ 48 - 0
pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/MinioProperties.java

@@ -0,0 +1,48 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.common.minio;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * minio 配置信息
+ *
+ * @author lengleng
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "minio")
+public class MinioProperties {
+	/**
+	 * minio 服务地址 http://ip:port
+	 */
+	private String url;
+
+	/**
+	 * 用户名
+	 */
+	private String accessKey;
+
+	/**
+	 * 密码
+	 */
+	private String secretKey;
+
+}

+ 122 - 0
pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/http/MinioEndpoint.java

@@ -0,0 +1,122 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.common.minio.http;
+
+import com.pig4cloud.common.minio.service.MinioTemplate;
+import com.pig4cloud.common.minio.vo.MinioItem;
+import com.pig4cloud.common.minio.vo.MinioObject;
+import io.minio.messages.Bucket;
+import lombok.AllArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * minio 对外提供服务端点
+ *
+ * @author lengleng
+ * <p>
+ * minio.endpoint.enable
+ */
+@ConditionalOnProperty(name = "minio.endpoint.enable", havingValue = "true")
+@RestController
+@AllArgsConstructor
+@RequestMapping("${minio.endpoint.name:/minio}")
+public class MinioEndpoint {
+	private final MinioTemplate template;
+
+	/**
+	 * Bucket Endpoints
+	 */
+	@PostMapping("/bucket/{bucketName}")
+	public Bucket createBucker(@PathVariable String bucketName) throws Exception {
+
+		template.createBucket(bucketName);
+		return template.getBucket(bucketName).get();
+
+	}
+
+	@GetMapping("/bucket")
+	public List<Bucket> getBuckets() throws Exception {
+		return template.getAllBuckets();
+	}
+
+	@GetMapping("/bucket/{bucketName}")
+	public Bucket getBucket(@PathVariable String bucketName) throws Exception {
+		return template.getBucket(bucketName).orElseThrow(() -> new IllegalArgumentException("Bucket Name not found!"));
+	}
+
+	@DeleteMapping("/bucket/{bucketName}")
+	@ResponseStatus(HttpStatus.ACCEPTED)
+	public void deleteBucket(@PathVariable String bucketName) throws Exception {
+
+		template.removeBucket(bucketName);
+	}
+
+	/**
+	 * Object Endpoints
+	 */
+
+	@PostMapping("/object/{bucketName}")
+	public MinioObject createObject(@RequestBody MultipartFile object, @PathVariable String bucketName) throws Exception {
+		String name = object.getOriginalFilename();
+		template.putObject(bucketName, name, object.getInputStream(), object.getSize(), object.getContentType());
+		return new MinioObject(template.getObjectInfo(bucketName, name));
+
+	}
+
+	@PostMapping("/object/{bucketName}/{objectName}")
+	public MinioObject createObject(@RequestBody MultipartFile object, @PathVariable String bucketName, @PathVariable String objectName) throws Exception {
+		template.putObject(bucketName, objectName, object.getInputStream(), object.getSize(), object.getContentType());
+		return new MinioObject(template.getObjectInfo(bucketName, objectName));
+
+	}
+
+
+	@GetMapping("/object/{bucketName}/{objectName}")
+	public List<MinioItem> filterObject(@PathVariable String bucketName, @PathVariable String objectName) throws Exception {
+
+		return template.getAllObjectsByPrefix(bucketName, objectName, true);
+
+	}
+
+	@GetMapping("/object/{bucketName}/{objectName}/{expires}")
+	public Map<String, Object> getObject(@PathVariable String bucketName, @PathVariable String objectName, @PathVariable Integer expires) throws Exception {
+		Map<String, Object> responseBody = new HashMap<>(8);
+		// Put Object info
+		responseBody.put("bucket", bucketName);
+		responseBody.put("object", objectName);
+		responseBody.put("url", template.getObjectURL(bucketName, objectName, expires));
+		responseBody.put("expires", expires);
+		return responseBody;
+	}
+
+	@DeleteMapping("/object/{bucketName}/{objectName}/")
+	@ResponseStatus(HttpStatus.ACCEPTED)
+	public void deleteObject(@PathVariable String bucketName, @PathVariable String objectName) throws Exception {
+
+		template.removeObject(bucketName, objectName);
+	}
+
+
+}

+ 189 - 0
pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java

@@ -0,0 +1,189 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.common.minio.service;
+
+import com.pig4cloud.common.minio.vo.MinioItem;
+import io.minio.MinioClient;
+import io.minio.ObjectStat;
+import io.minio.Result;
+import io.minio.messages.Bucket;
+import io.minio.messages.Item;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * minio 交互类
+ *
+ * @author lengleng
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+public class MinioTemplate {
+
+	private String endpoint;
+	private String accessKey;
+	private String secretKey;
+
+
+	/**
+	 * 创建bucket
+	 *
+	 * @param bucketName bucket名称
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#makeBucket
+	 */
+	public void createBucket(String bucketName) throws Exception {
+		MinioClient client = getMinioClient();
+		if (!client.bucketExists(bucketName)) {
+			client.makeBucket(bucketName);
+		}
+	}
+
+	/**
+	 * 获取全部bucket
+	 * <p>
+	 * https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
+	 */
+	public List<Bucket> getAllBuckets() throws Exception {
+		return getMinioClient().listBuckets();
+	}
+
+	/**
+	 * @param bucketName bucket名称
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
+	 */
+	public Optional<Bucket> getBucket(String bucketName) throws Exception {
+		return getMinioClient().listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
+	}
+
+	/**
+	 * @param bucketName bucket名称
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeBucket
+	 */
+	public void removeBucket(String bucketName) throws Exception {
+		getMinioClient().removeBucket(bucketName);
+	}
+
+	/**
+	 * 根据文件前置查询文件
+	 *
+	 * @param bucketName bucket名称
+	 * @param prefix     前缀
+	 * @param recursive  是否递归查询
+	 * @return
+	 * @throws Exception
+	 */
+	public List<MinioItem> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) throws Exception {
+		List objectList = new ArrayList();
+		Iterable<Result<Item>> objectsIterator = getMinioClient()
+				.listObjects(bucketName, prefix, recursive);
+
+		while (objectsIterator.iterator().hasNext()) {
+			objectList.add(objectsIterator.iterator().next().get());
+		}
+		return objectList;
+	}
+
+	/**
+	 * 获取文件外链
+	 *
+	 * @param bucketName bucket名称
+	 * @param objectName 文件名称
+	 * @param expires    过期时间 <=7
+	 * @return url
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#getObject
+	 */
+	public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
+		return getMinioClient().presignedGetObject(bucketName, objectName, expires);
+	}
+
+	/**
+	 * 获取文件
+	 *
+	 * @param bucketName bucket名称
+	 * @param objectName 文件名称
+	 * @return 二进制流
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#getObject
+	 */
+	public InputStream getObject(String bucketName, String objectName) throws Exception {
+		return getMinioClient().getObject(bucketName, objectName);
+	}
+
+	/**
+	 * 上传文件
+	 *
+	 * @param bucketName bucket名称
+	 * @param objectName 文件名称
+	 * @param stream     文件流
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
+	 */
+	public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
+		getMinioClient().putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");
+	}
+
+	/**
+	 * 上传文件
+	 *
+	 * @param bucketName  bucket名称
+	 * @param objectName  文件名称
+	 * @param stream      文件流
+	 * @param size        大小
+	 * @param contextType 类型
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
+	 */
+	public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
+		getMinioClient().putObject(bucketName, objectName, stream, size, contextType);
+	}
+
+	/**
+	 * 获取文件信息
+	 *
+	 * @param bucketName bucket名称
+	 * @param objectName 文件名称
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
+	 */
+	public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception {
+		return getMinioClient().statObject(bucketName, objectName);
+	}
+
+	/**
+	 * 删除文件
+	 *
+	 * @param bucketName bucket名称
+	 * @param objectName 文件名称
+	 * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject
+	 */
+	public void removeObject(String bucketName, String objectName) throws Exception {
+		getMinioClient().removeObject(bucketName, objectName);
+	}
+
+
+	/**
+	 * 获取minio 原生客户端
+	 *
+	 * @return
+	 * @throws Exception
+	 */
+	public MinioClient getMinioClient() throws Exception {
+		return new MinioClient(endpoint, accessKey, secretKey);
+	}
+}

+ 53 - 0
pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/vo/MinioItem.java

@@ -0,0 +1,53 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.common.minio.vo;
+
+import io.minio.messages.Item;
+import io.minio.messages.Owner;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * minio 桶中的对象信息
+ *
+ * @author lengleng
+ */
+@Data
+@AllArgsConstructor
+public class MinioItem {
+
+	private String objectName;
+	private Date lastModified;
+	private String etag;
+	private Long size;
+	private String storageClass;
+	private Owner owner;
+	private String type;
+
+	public MinioItem(Item item) {
+		this.objectName = item.objectName();
+		this.lastModified = item.lastModified();
+		this.etag = item.etag();
+		this.size = (long) item.size();
+		this.storageClass = item.storageClass();
+		this.owner = item.owner();
+		this.type = item.isDir() ? "directory" : "file";
+	}
+}

+ 53 - 0
pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/vo/MinioObject.java

@@ -0,0 +1,53 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.common.minio.vo;
+
+import io.minio.ObjectStat;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.util.Date;
+
+
+/**
+ * 存储对象的元数据
+ *
+ * @author lengleng
+ */
+@Data
+@AllArgsConstructor
+public class MinioObject {
+	private String bucketName;
+	private String name;
+	private Date createdTime;
+	private Long length;
+	private String etag;
+	private String contentType;
+	private String matDesc;
+
+	public MinioObject(ObjectStat os) {
+		this.bucketName = os.bucketName();
+		this.name = os.name();
+		this.createdTime = os.createdTime();
+		this.length = os.length();
+		this.etag = os.etag();
+		this.contentType = os.contentType();
+		this.matDesc = os.matDesc();
+	}
+
+}

+ 2 - 0
pigx-common/pigx-common-minio/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.pig4cloud.common.minio.MinioAutoConfiguration

+ 1 - 0
pigx-common/pom.xml

@@ -38,6 +38,7 @@
 		<module>pigx-common-gateway</module>
 		<module>pigx-common-job</module>
 		<module>pigx-common-log</module>
+		<module>pigx-common-minio</module>
 		<module>pigx-common-security</module>
 		<module>pigx-common-swagger</module>
 		<module>pigx-common-transaction</module>

+ 1 - 0
pom.xml

@@ -58,6 +58,7 @@
 		<lcn.version>4.1.0</lcn.version>
 		<jasypt.version>2.1.0</jasypt.version>
 		<ttl.version>2.10.1</ttl.version>
+		<minio.version>3.0.12</minio.version>
 		<elastic-job-lite.version>2.1.5</elastic-job-lite.version>
 		<mysql.connector.version>8.0.13</mysql.connector.version>
 		<security.oauth.version>2.3.3.RELEASE</security.oauth.version>