feat: 添加 spring-boot-storage starter.
This commit is contained in:
@@ -107,6 +107,11 @@
|
||||
<artifactId>orion-ops-spring-boot-starter-log</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.orion.ops</groupId>
|
||||
<artifactId>orion-ops-spring-boot-starter-storage</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- websocket -->
|
||||
<dependency>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<groupId>com.orion.ops</groupId>
|
||||
<artifactId>orion-ops-framework</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>orion-ops-spring-boot-starter-storage</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<description>项目存储层配置包</description>
|
||||
<url>https://github.com/lijiahangmax/orion-ops-pro</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.orion.ops</groupId>
|
||||
<artifactId>orion-ops-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.orion.ops.framework.storage.config;
|
||||
|
||||
import com.orion.ops.framework.storage.core.client.FileClient;
|
||||
import com.orion.ops.framework.storage.core.client.local.LocalFileClient;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
/**
|
||||
* 存储配置类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/6/30 16:21
|
||||
* <p>
|
||||
* TODO 后续添加 FAST MINIO OSS 等
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(StorageConfig.class)
|
||||
public class OrionStorageAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 本地文件客户端
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
public FileClient localFileClient(StorageConfig config) {
|
||||
return new LocalFileClient(config.getLocal());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.orion.ops.framework.storage.config;
|
||||
|
||||
import com.orion.ops.framework.storage.core.client.local.LocalFileClientConfig;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* 存储配置
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/6/30 18:40
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "orion.storage")
|
||||
public class StorageConfig {
|
||||
|
||||
/**
|
||||
* 本地文件客户端 配置
|
||||
*/
|
||||
private LocalFileClientConfig local;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.orion.ops.framework.storage.core.client;
|
||||
|
||||
import com.orion.lang.id.UUIds;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
import com.orion.ops.framework.common.meta.TraceIdHolder;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 文件客户端 基类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/6/30 17:24
|
||||
*/
|
||||
public abstract class AbstractFileClient<Config extends FileClientConfig> implements FileClient {
|
||||
|
||||
protected Config config;
|
||||
|
||||
public AbstractFileClient(Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(String path, byte[] content) throws Exception {
|
||||
return this.doUpload(path, Streams.toInputStream(content), true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(String path, byte[] content, boolean overrideIfExist) throws Exception {
|
||||
return this.doUpload(path, Streams.toInputStream(content), true, overrideIfExist);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(String path, InputStream in) throws Exception {
|
||||
return this.doUpload(path, in, false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(String path, InputStream in, boolean autoClose) throws Exception {
|
||||
return this.doUpload(path, in, autoClose, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(String path, InputStream in, boolean autoClose, boolean overrideIfExist) throws Exception {
|
||||
return this.doUpload(path, in, autoClose, overrideIfExist);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent(String path) throws Exception {
|
||||
try (InputStream in = this.doDownload(path)) {
|
||||
return Streams.toByteArray(in);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getContentInputStream(String path) throws Exception {
|
||||
return this.doDownload(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行上传操作
|
||||
*
|
||||
* @param path path
|
||||
* @param in in
|
||||
* @param autoClose autoClose
|
||||
* @param overrideIfExist 文件存在是否覆盖
|
||||
* @return path
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
protected abstract String doUpload(String path, InputStream in, boolean autoClose, boolean overrideIfExist) throws Exception;
|
||||
|
||||
/**
|
||||
* 执行下载操作
|
||||
*
|
||||
* @param path path
|
||||
* @return stream
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
protected abstract InputStream doDownload(String path) throws Exception;
|
||||
|
||||
/**
|
||||
* 获取返回路径 用于客户端返回
|
||||
*
|
||||
* @param path path
|
||||
* @return returnPath
|
||||
*/
|
||||
protected abstract String getReturnPath(String path);
|
||||
|
||||
/**
|
||||
* 获取实际存储路径 用于服务端的存储
|
||||
*
|
||||
* @param returnPath returnPath
|
||||
* @return absolutePath
|
||||
*/
|
||||
protected abstract String getAbsolutePath(String returnPath);
|
||||
|
||||
/**
|
||||
* 获取文件路径 拼接前缀
|
||||
*
|
||||
* @param path 路径
|
||||
* @return 文件名称
|
||||
*/
|
||||
protected String getFilePath(String path) {
|
||||
// 无需拼接
|
||||
if (!config.isNameAppendTraceId()) {
|
||||
return path;
|
||||
}
|
||||
// 名称前缀
|
||||
String traceId = TraceIdHolder.get();
|
||||
if (traceId == null) {
|
||||
traceId = UUIds.random32();
|
||||
}
|
||||
String prefix = traceId + "_";
|
||||
String name = Files1.getFileName(path);
|
||||
// 只是文件名
|
||||
if (name.equals(path)) {
|
||||
return prefix + name;
|
||||
}
|
||||
// 包含路径
|
||||
String parentPath = Files1.getParentPath(path);
|
||||
return parentPath + prefix + name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.orion.ops.framework.storage.core.client;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 文件客户端
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/6/30 16:51
|
||||
*/
|
||||
public interface FileClient {
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param content 文件内容
|
||||
* @return 路径
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
String upload(String path, byte[] content) throws Exception;
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param content 文件内容
|
||||
* @param overrideIfExist 文件存在是否覆盖
|
||||
* @return 路径
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
String upload(String path, byte[] content, boolean overrideIfExist) throws Exception;
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param in in
|
||||
* @return 路径
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
String upload(String path, InputStream in) throws Exception;
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param in in
|
||||
* @param autoClose autoClose
|
||||
* @return 路径
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
String upload(String path, InputStream in, boolean autoClose) throws Exception;
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param in in
|
||||
* @param autoClose autoClose
|
||||
* @param overrideIfExist 文件存在是否覆盖
|
||||
* @return 路径
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
String upload(String path, InputStream in, boolean autoClose, boolean overrideIfExist) throws Exception;
|
||||
|
||||
/**
|
||||
* 检测文件是否存在
|
||||
*
|
||||
* @param path path
|
||||
* @return 是否存在
|
||||
*/
|
||||
boolean isExists(String path);
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param path 路径
|
||||
* @return 是否删除
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
boolean delete(String path) throws Exception;
|
||||
|
||||
/**
|
||||
* 获取文件内容
|
||||
*
|
||||
* @param path path
|
||||
* @return bytes
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
byte[] getContent(String path) throws Exception;
|
||||
|
||||
/**
|
||||
* 获取文件输入流
|
||||
*
|
||||
* @param path path
|
||||
* @return stream
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
InputStream getContentInputStream(String path) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.orion.ops.framework.storage.core.client;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 文件客户端配置 基类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/6/30 17:21
|
||||
*/
|
||||
@Data
|
||||
public class FileClientConfig {
|
||||
|
||||
/**
|
||||
* 是否自动拼接 traceId 前缀. 没有则使用 UUID
|
||||
*/
|
||||
protected boolean nameAppendTraceId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.orion.ops.framework.storage.core.client.local;
|
||||
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
import com.orion.ops.framework.storage.core.client.AbstractFileClient;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* 本地文件客户端
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/6/30 17:21
|
||||
*/
|
||||
public class LocalFileClient extends AbstractFileClient<LocalFileClientConfig> {
|
||||
|
||||
public LocalFileClient(LocalFileClientConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doUpload(String path, InputStream in, boolean autoClose, boolean overrideIfExist) throws Exception {
|
||||
// 获取返回文件路径
|
||||
String returnPath = this.getReturnPath(path);
|
||||
// 检测文件是否存在
|
||||
if (!overrideIfExist && this.isExists(returnPath)) {
|
||||
return returnPath;
|
||||
}
|
||||
// 获取实际文件路径
|
||||
String absolutePath = this.getAbsolutePath(returnPath);
|
||||
// 上传文件
|
||||
try (OutputStream out = Files1.openOutputStreamFast(absolutePath)) {
|
||||
Streams.transfer(in, out);
|
||||
} finally {
|
||||
if (autoClose) {
|
||||
Streams.close(in);
|
||||
}
|
||||
}
|
||||
return returnPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream doDownload(String path) throws Exception {
|
||||
return Files1.openInputStreamFast(this.getAbsolutePath(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExists(String path) {
|
||||
return Files1.isFile(this.getAbsolutePath(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(String path) {
|
||||
return Files1.delete(this.getAbsolutePath(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getReturnPath(String path) {
|
||||
// 拼接前缀
|
||||
return Files1.getPath(config.getBasePath() + "/" + this.getFilePath(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAbsolutePath(String returnPath) {
|
||||
// 拼接存储路径
|
||||
return Files1.getPath(config.getStoragePath() + "/" + returnPath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.orion.ops.framework.storage.core.client.local;
|
||||
|
||||
import com.orion.ops.framework.storage.core.client.FileClientConfig;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 本地文件客户端 配置
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/6/30 17:47
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class LocalFileClientConfig extends FileClientConfig {
|
||||
|
||||
/**
|
||||
* 存储路径
|
||||
* <p>
|
||||
* 无需 / 结尾
|
||||
*/
|
||||
private String storagePath = "";
|
||||
|
||||
/**
|
||||
* 基础路径
|
||||
* <p>
|
||||
* 无需 / 结尾
|
||||
*/
|
||||
private String basePath = "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"name": "orion.storage",
|
||||
"type": "com.orion.ops.framework.storage.config.StorageConfig",
|
||||
"sourceType": "com.orion.ops.framework.storage.config.StorageConfig"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "orion.storage.local.nameAppendTraceId",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "是否自动拼接 traceId 前缀. 没有则使用 UUID.",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"name": "orion.storage.local.storagePath",
|
||||
"type": "java.lang.String",
|
||||
"description": "存储路径.",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "orion.storage.local.basePath",
|
||||
"type": "java.lang.String",
|
||||
"description": "基础路径.",
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
com.orion.ops.framework.storage.config.OrionStorageAutoConfiguration
|
||||
@@ -27,6 +27,7 @@
|
||||
<module>orion-ops-spring-boot-starter-redis</module>
|
||||
<module>orion-ops-spring-boot-starter-desensitize</module>
|
||||
<module>orion-ops-spring-boot-starter-log</module>
|
||||
<module>orion-ops-spring-boot-starter-storage</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
@@ -64,6 +64,11 @@
|
||||
<groupId>com.orion.ops</groupId>
|
||||
<artifactId>orion-ops-spring-boot-starter-log</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.orion.ops</groupId>
|
||||
<artifactId>orion-ops-spring-boot-starter-storage</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- orion-ops biz-modules -->
|
||||
|
||||
|
||||
@@ -139,3 +139,8 @@ orion:
|
||||
email: ljh1553488six@139.com
|
||||
license: Apache-2.0
|
||||
license-url: https://github.com/lijiahangmax/orion-ops-pro/blob/main/LICENSE
|
||||
storage:
|
||||
local:
|
||||
nameAppendTraceId: true
|
||||
storagePath: ${user.home}
|
||||
basePath: /orion/storage/orion-ops-pro
|
||||
|
||||
Reference in New Issue
Block a user