diff --git a/fast-boot-api/pom.xml b/fast-boot-api/pom.xml
new file mode 100644
index 0000000..ac85377
--- /dev/null
+++ b/fast-boot-api/pom.xml
@@ -0,0 +1,18 @@
+
+
+ net.maku
+ fast-boot
+ 1.0.0
+
+ 4.0.0
+ fast-boot-api
+ jar
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
\ No newline at end of file
diff --git a/fast-boot-api/src/main/java/net/maku/api/module/storage/StorageService.java b/fast-boot-api/src/main/java/net/maku/api/module/storage/StorageService.java
new file mode 100644
index 0000000..b115150
--- /dev/null
+++ b/fast-boot-api/src/main/java/net/maku/api/module/storage/StorageService.java
@@ -0,0 +1,67 @@
+package net.maku.api.module.storage;
+
+import org.springframework.util.StringUtils;
+
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * 存储服务
+ *
+ * @author 阿沐 babamu@126.com
+ */
+public interface StorageService {
+ /**
+ * 文件路径
+ * @param prefix 前缀
+ * @param suffix 后缀
+ * @return 返回上传路径
+ */
+ default String getPath(String prefix, String suffix) {
+ //生成uuid
+ String uuid = UUID.randomUUID().toString().replaceAll("-", "");
+ //文件路径
+ SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
+ String path = df.format(new Date()) + "/" + uuid;
+
+ if(StringUtils.hasText(prefix)){
+ path = prefix + "/" + path;
+ }
+
+ return path + "." + suffix;
+ }
+
+ /**
+ * 文件上传
+ * @param data 文件字节数组
+ * @param path 文件路径,包含文件名
+ * @return 返回http地址
+ */
+ String upload(byte[] data, String path);
+
+ /**
+ * 文件上传
+ * @param data 文件字节数组
+ * @param suffix 后缀
+ * @return 返回http地址
+ */
+ String uploadSuffix(byte[] data, String suffix);
+
+ /**
+ * 文件上传
+ * @param inputStream 字节流
+ * @param path 文件路径,包含文件名
+ * @return 返回http地址
+ */
+ String upload(InputStream inputStream, String path);
+
+ /**
+ * 文件上传
+ * @param inputStream 字节流
+ * @param suffix 后缀
+ * @return 返回http地址
+ */
+ String uploadSuffix(InputStream inputStream, String suffix);
+}
diff --git a/fast-boot-system/pom.xml b/fast-boot-system/pom.xml
index 42bbd87..2a7d59a 100644
--- a/fast-boot-system/pom.xml
+++ b/fast-boot-system/pom.xml
@@ -15,6 +15,15 @@
1.0.0
+ net.maku
+ fast-boot-api
+ 1.0.0
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+
+
com.github.whvcse
easy-captcha
diff --git a/fast-boot-system/src/main/java/net/maku/storage/config/LocalResourceConfiguration.java b/fast-boot-system/src/main/java/net/maku/storage/config/LocalResourceConfiguration.java
new file mode 100644
index 0000000..e2c758d
--- /dev/null
+++ b/fast-boot-system/src/main/java/net/maku/storage/config/LocalResourceConfiguration.java
@@ -0,0 +1,35 @@
+package net.maku.storage.config;
+
+import net.maku.storage.enums.StorageTypeEnum;
+import net.maku.storage.properties.LocalStorageProperties;
+import net.maku.storage.properties.StorageProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import javax.annotation.Resource;
+
+/**
+ * 本地资源映射配置
+ *
+ * @author 阿沐 babamu@126.com
+ */
+@Configuration
+@ConditionalOnProperty(prefix = "storage", value = "enabled")
+public class LocalResourceConfiguration implements WebMvcConfigurer {
+ @Resource
+ private StorageProperties properties;
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ // 如果不是本地存储,则返回
+ if(properties.getConfig().getType() != StorageTypeEnum.LOCAL){
+ return;
+ }
+
+ LocalStorageProperties local = properties.getLocal();
+ registry.addResourceHandler("/" + local.getUrl() + "/**")
+ .addResourceLocations("file:" + local.getPath() + "/");
+ }
+}
\ No newline at end of file
diff --git a/fast-boot-system/src/main/java/net/maku/storage/config/StorageConfiguration.java b/fast-boot-system/src/main/java/net/maku/storage/config/StorageConfiguration.java
new file mode 100644
index 0000000..bae6ba0
--- /dev/null
+++ b/fast-boot-system/src/main/java/net/maku/storage/config/StorageConfiguration.java
@@ -0,0 +1,34 @@
+package net.maku.storage.config;
+
+import net.maku.api.module.storage.StorageService;
+import net.maku.storage.enums.StorageTypeEnum;
+import net.maku.storage.properties.StorageProperties;
+import net.maku.storage.service.AliyunStorageService;
+import net.maku.storage.service.LocalStorageService;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 存储配置文件
+ *
+ * @author 阿沐 babamu@126.com
+ */
+@Configuration
+@EnableConfigurationProperties(StorageProperties.class)
+@ConditionalOnProperty(prefix = "storage", value = "enabled")
+public class StorageConfiguration {
+
+ @Bean
+ public StorageService storageService(StorageProperties properties){
+ if(properties.getConfig().getType() == StorageTypeEnum.LOCAL){
+ return new LocalStorageService(properties);
+ }else if(properties.getConfig().getType() == StorageTypeEnum.ALIYUN){
+ return new AliyunStorageService(properties);
+ }
+
+ return null;
+ }
+
+}
diff --git a/fast-boot-system/src/main/java/net/maku/storage/enums/StorageTypeEnum.java b/fast-boot-system/src/main/java/net/maku/storage/enums/StorageTypeEnum.java
new file mode 100644
index 0000000..456f154
--- /dev/null
+++ b/fast-boot-system/src/main/java/net/maku/storage/enums/StorageTypeEnum.java
@@ -0,0 +1,17 @@
+package net.maku.storage.enums;
+
+/**
+ * 存储类型枚举
+ *
+ * @author 阿沐 babamu@126.com
+ */
+public enum StorageTypeEnum {
+ /**
+ * 本地
+ */
+ LOCAL,
+ /**
+ * 阿里云
+ */
+ ALIYUN;
+}
diff --git a/fast-boot-system/src/main/java/net/maku/storage/properties/AliyunStorageProperties.java b/fast-boot-system/src/main/java/net/maku/storage/properties/AliyunStorageProperties.java
new file mode 100644
index 0000000..43625b3
--- /dev/null
+++ b/fast-boot-system/src/main/java/net/maku/storage/properties/AliyunStorageProperties.java
@@ -0,0 +1,16 @@
+package net.maku.storage.properties;
+
+import lombok.Data;
+
+/**
+ * 阿里云存储配置项
+ *
+ * @author 阿沐 babamu@126.com
+ */
+@Data
+public class AliyunStorageProperties {
+ private String endPoint;
+ private String accessKeyId;
+ private String accessKeySecret;
+ private String bucketName;
+}
diff --git a/fast-boot-system/src/main/java/net/maku/storage/properties/LocalStorageProperties.java b/fast-boot-system/src/main/java/net/maku/storage/properties/LocalStorageProperties.java
new file mode 100644
index 0000000..d263f48
--- /dev/null
+++ b/fast-boot-system/src/main/java/net/maku/storage/properties/LocalStorageProperties.java
@@ -0,0 +1,20 @@
+package net.maku.storage.properties;
+
+import lombok.Data;
+
+/**
+ * 本地存储配置项
+ *
+ * @author 阿沐 babamu@126.com
+ */
+@Data
+public class LocalStorageProperties {
+ /**
+ * 本地存储路径
+ */
+ private String path;
+ /**
+ * 资源起始路径
+ */
+ private String url = "upload";
+}
diff --git a/fast-boot-system/src/main/java/net/maku/storage/properties/StorageProperties.java b/fast-boot-system/src/main/java/net/maku/storage/properties/StorageProperties.java
new file mode 100644
index 0000000..29a08cf
--- /dev/null
+++ b/fast-boot-system/src/main/java/net/maku/storage/properties/StorageProperties.java
@@ -0,0 +1,47 @@
+package net.maku.storage.properties;
+
+import lombok.Data;
+import net.maku.storage.enums.StorageTypeEnum;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * 存储配置项
+ *
+ * @author 阿沐 babamu@126.com
+ */
+@Data
+@ConfigurationProperties(prefix = "storage")
+public class StorageProperties {
+ /**
+ * 是否开启存储
+ */
+ private boolean enabled;
+ /**
+ * 通用配置项
+ */
+ private StorageConfig config;
+ /**
+ * 本地配置项
+ */
+ private LocalStorageProperties local;
+ /**
+ * 阿里云配置项
+ */
+ private AliyunStorageProperties aliyun;
+
+ @Data
+ public static class StorageConfig{
+ /**
+ * 访问域名
+ */
+ private String domain;
+ /**
+ * 配置路径前缀
+ */
+ private String prefix;
+ /**
+ * 存储类型
+ */
+ private StorageTypeEnum type;
+ }
+}
diff --git a/fast-boot-system/src/main/java/net/maku/storage/service/AliyunStorageService.java b/fast-boot-system/src/main/java/net/maku/storage/service/AliyunStorageService.java
new file mode 100644
index 0000000..aa0a0c6
--- /dev/null
+++ b/fast-boot-system/src/main/java/net/maku/storage/service/AliyunStorageService.java
@@ -0,0 +1,55 @@
+package net.maku.storage.service;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import net.maku.api.module.storage.StorageService;
+import net.maku.framework.common.exception.FastException;
+import net.maku.storage.properties.StorageProperties;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+/**
+ * 阿里云存储
+ *
+ * @author 阿沐 babamu@126.com
+ */
+public class AliyunStorageService implements StorageService {
+ private final StorageProperties properties;
+
+ public AliyunStorageService(StorageProperties properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public String upload(byte[] data, String path) {
+ return upload(new ByteArrayInputStream(data), path);
+ }
+
+ @Override
+ public String uploadSuffix(byte[] data, String suffix) {
+ return upload(data, getPath(properties.getConfig().getPrefix(), suffix));
+ }
+
+ @Override
+ public String upload(InputStream inputStream, String path) {
+ OSS client = new OSSClientBuilder().build(properties.getAliyun().getEndPoint(),
+ properties.getAliyun().getAccessKeyId(), properties.getAliyun().getAccessKeySecret());
+ try {
+ client.putObject(properties.getAliyun().getBucketName(), path, inputStream);
+ }catch (Exception e){
+ throw new FastException("上传文件失败:", e);
+ } finally {
+ if (client != null) {
+ client.shutdown();
+ }
+ }
+
+ return properties.getConfig().getDomain() + "/" + path;
+ }
+
+ @Override
+ public String uploadSuffix(InputStream inputStream, String suffix) {
+ return upload(inputStream, getPath(properties.getConfig().getPrefix(), suffix));
+ }
+}
diff --git a/fast-boot-system/src/main/java/net/maku/storage/service/LocalStorageService.java b/fast-boot-system/src/main/java/net/maku/storage/service/LocalStorageService.java
new file mode 100644
index 0000000..2202c3c
--- /dev/null
+++ b/fast-boot-system/src/main/java/net/maku/storage/service/LocalStorageService.java
@@ -0,0 +1,60 @@
+package net.maku.storage.service;
+
+import net.maku.api.module.storage.StorageService;
+import net.maku.framework.common.exception.FastException;
+import net.maku.storage.properties.StorageProperties;
+import org.springframework.util.FileCopyUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+
+/**
+ * 本地存储
+ *
+ * @author 阿沐 babamu@126.com
+ */
+public class LocalStorageService implements StorageService {
+ private final StorageProperties properties;
+
+ public LocalStorageService(StorageProperties properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public String upload(byte[] data, String path) {
+ return upload(new ByteArrayInputStream(data), path);
+ }
+
+ @Override
+ public String uploadSuffix(byte[] data, String suffix) {
+ return upload(data, getPath(properties.getConfig().getPrefix(), suffix));
+ }
+
+ @Override
+ public String upload(InputStream inputStream, String path) {
+
+ try {
+ File file = new File(properties.getLocal().getPath() + File.separator + path);
+
+ // 没有目录,则自动创建目录
+ File parent = file.getParentFile();
+ if (parent != null && !parent.mkdirs() && !parent.isDirectory()) {
+ throw new IOException("Directory '" + parent + "' could not be created");
+ }
+
+ FileCopyUtils.copy(inputStream, Files.newOutputStream(file.toPath()));
+ } catch (Exception e) {
+ throw new FastException("上传文件失败:", e);
+ }
+
+ return properties.getConfig().getDomain() + "/" + properties.getLocal().getUrl() + "/" + path;
+ }
+
+ @Override
+ public String uploadSuffix(InputStream inputStream, String suffix) {
+ return upload(inputStream, getPath(properties.getConfig().getPrefix(), suffix));
+ }
+}
diff --git a/fast-boot-system/src/main/resources/auth.yml b/fast-boot-system/src/main/resources/auth.yml
index e0a9b12..a8a14e3 100644
--- a/fast-boot-system/src/main/resources/auth.yml
+++ b/fast-boot-system/src/main/resources/auth.yml
@@ -8,4 +8,5 @@ auth:
- /swagger-ui.html
- /swagger-ui/**
- /doc.html
- - /sys/oauth/captcha
\ No newline at end of file
+ - /sys/oauth/captcha
+ - /upload/**
\ No newline at end of file
diff --git a/fast-server/src/main/resources/application.yml b/fast-server/src/main/resources/application.yml
index 6436fe1..71aa526 100644
--- a/fast-server/src/main/resources/application.yml
+++ b/fast-server/src/main/resources/application.yml
@@ -21,6 +21,18 @@ spring:
max-file-size: 1024MB
max-request-size: 1024MB
+storage:
+ enabled: true
+ config:
+ # 存储类型:local、aliyun
+ type: local
+ # 访问域名
+ domain: http://localhost:8080
+ # 配置访问前缀
+ prefix:
+ local:
+ # 本地上传路径
+ path: D://upload
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
diff --git a/fast-server/src/test/java/net/maku/FileUploadTest.java b/fast-server/src/test/java/net/maku/FileUploadTest.java
new file mode 100644
index 0000000..7e2f4d8
--- /dev/null
+++ b/fast-server/src/test/java/net/maku/FileUploadTest.java
@@ -0,0 +1,24 @@
+package net.maku;
+
+import cn.hutool.core.io.IoUtil;
+import net.maku.api.module.storage.StorageService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.io.File;
+import java.nio.file.Files;
+
+@SpringBootTest
+public class FileUploadTest {
+ @Autowired
+ private StorageService storageService;
+
+ @Test
+ public void uploadTest() throws Exception{
+ byte[] data = IoUtil.readBytes(Files.newInputStream(new File("D://upload//1.png").toPath()));
+ String url = storageService.uploadSuffix(data, "png");
+ System.out.println(url);
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 91133fa..13b37df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,8 +17,9 @@
- fast-boot-system
fast-boot-new
+ fast-boot-system
+ fast-boot-api
fast-framework
fast-server
@@ -34,6 +35,7 @@
2.3.8.RELEASE
1.6.2
1.4.2.Final
+ 3.8.0
@@ -103,6 +105,11 @@
mapstruct-processor
${mapstruct.version}
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+ ${aliyun.oss.version}
+