diff --git a/README.md b/README.md
index e47fbcc..a4de831 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,30 @@
**PlayEdu** 是基于 Java + SpringBoot3.0 开发的开源的企业、机构、大学院校的内部培训解决方案。
+### 开始上手
+
+使用 `docker` 安装 `minio` :
+
+> 下面是测试环境安装的 minio .
+
+```
+docker run -p 9000:9000 -p 50000:50000 -d --name playedu-minio \
+ -e "MINIO_ACCESS_KEY=username" \
+ -e "MINIO_SECRET_KEY=password" \
+ minio/minio server --console-address ":50000" /data
+```
+
+如果您想在生产环境中使用,推荐您做好数据卷的挂载并自行配置 `AccessKey` 和 `SecretKey` :
+
+```
+docker run -p 9000:9000 -p 50000:50000 -d --name playedu-minio \
+ -e "MINIO_ACCESS_KEY=自定义用户名" \
+ -e "MINIO_SECRET_KEY=自定义密码" \
+ -v /mnt/data:/data \
+ -v /mnt/config:/root/.minio \
+ minio/minio server --console-address ":50000" /data
+```
+
### 使用协议
欢迎使用杭州白书科技有限公司提供的开源培训解决方案!请您仔细阅读以下条款。通过使用 PlayEdu ,您表示同意接受以下所有条款。
diff --git a/pom.xml b/pom.xml
index 38e7c70..f51e4fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -117,6 +117,17 @@
compile
+
+ cn.xuyanwu
+ spring-file-storage
+ 0.7.0
+
+
+ io.minio
+ minio
+ 8.4.3
+
+
diff --git a/src/main/java/xyz/playedu/api/PlayeduApiApplication.java b/src/main/java/xyz/playedu/api/PlayeduApiApplication.java
index a5524a3..23aaee0 100644
--- a/src/main/java/xyz/playedu/api/PlayeduApiApplication.java
+++ b/src/main/java/xyz/playedu/api/PlayeduApiApplication.java
@@ -1,11 +1,13 @@
package xyz.playedu.api;
+import cn.xuyanwu.spring.file.storage.EnableFileStorage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
+@EnableFileStorage
public class PlayeduApiApplication {
public static void main(String[] args) {
diff --git a/src/main/java/xyz/playedu/api/config/FileStorageConfig.java b/src/main/java/xyz/playedu/api/config/FileStorageConfig.java
new file mode 100644
index 0000000..cde9d6c
--- /dev/null
+++ b/src/main/java/xyz/playedu/api/config/FileStorageConfig.java
@@ -0,0 +1,27 @@
+package xyz.playedu.api.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Author 杭州白书科技有限公司
+ * @create 2023/2/28 16:38
+ */
+@Data
+@Configuration
+public class FileStorageConfig {
+
+ @Value("${spring.file-storage.default-platform}")
+ private String defaultPlatform;
+
+ @Value("${spring.file-storage.minio[0].domain}")
+ private String domain;
+
+ @Value("${spring.file-storage.minio[0].bucket-name}")
+ private String bucket;
+
+ @Value("${spring.file-storage.minio[0].base-path}")
+ private String basePath;
+
+}
diff --git a/src/main/java/xyz/playedu/api/constant/BackendConstant.java b/src/main/java/xyz/playedu/api/constant/BackendConstant.java
index b572c01..05efdc3 100644
--- a/src/main/java/xyz/playedu/api/constant/BackendConstant.java
+++ b/src/main/java/xyz/playedu/api/constant/BackendConstant.java
@@ -12,4 +12,6 @@ public class BackendConstant {
public final static String[] COURSE_HOUR_TYPE_WHITELIST = {"VIDEO"};
public final static String[] COURSE_HOUR_TYPE_WHITELIST_TEXT = {"视频"};
+ public final static String UPLOAD_IMAGE_DIR = "images/";
+
}
diff --git a/src/main/java/xyz/playedu/api/controller/backend/UploadController.java b/src/main/java/xyz/playedu/api/controller/backend/UploadController.java
new file mode 100644
index 0000000..c01854d
--- /dev/null
+++ b/src/main/java/xyz/playedu/api/controller/backend/UploadController.java
@@ -0,0 +1,70 @@
+package xyz.playedu.api.controller.backend;
+
+import cn.xuyanwu.spring.file.storage.FileInfo;
+import cn.xuyanwu.spring.file.storage.FileStorageService;
+import org.apache.commons.collections4.MapUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import xyz.playedu.api.bus.BackendBus;
+import xyz.playedu.api.config.FileStorageConfig;
+import xyz.playedu.api.constant.BackendConstant;
+import xyz.playedu.api.domain.Resource;
+import xyz.playedu.api.service.ResourceService;
+import xyz.playedu.api.types.JsonResponse;
+import xyz.playedu.api.util.HelperUtil;
+
+import java.util.Date;
+import java.util.HashMap;
+
+/**
+ * @Author 杭州白书科技有限公司
+ * @create 2023/2/28 16:26
+ */
+@RestController
+@RequestMapping("/backend/v1/upload")
+public class UploadController {
+
+ @Autowired
+ private FileStorageService fileStorageService;
+
+ @Autowired
+ private ResourceService resourceService;
+
+ @Autowired
+ private FileStorageConfig fileStorageConfig;
+
+ @PostMapping("/image")
+ public JsonResponse image(@RequestParam HashMap params, MultipartFile file) {
+ Integer categoryId = MapUtils.getInteger(params, "category_id", 0);
+ if (file == null || file.isEmpty()) {
+ return JsonResponse.error("请上传文件");
+ }
+ FileInfo fileInfo = fileStorageService
+ .of(file)
+ .setPath(fileStorageConfig.getBasePath() + BackendConstant.UPLOAD_IMAGE_DIR)
+ .setObjectId(HelperUtil.randomString(32))
+ .upload();
+
+ String savePath = fileInfo.getPath() + fileInfo.getFilename();
+ String url = fileStorageConfig.getDomain() + fileStorageConfig.getBucket() + "/" + savePath;
+
+ Resource resource = new Resource();
+ resource.setCategoryId(categoryId);
+ resource.setName(fileInfo.getFilename());
+ resource.setExtension(fileInfo.getExt());
+ resource.setSize(fileInfo.getSize());
+ resource.setDisk(fileStorageConfig.getDefaultPlatform());
+ resource.setFileId(fileInfo.getObjectId());
+ resource.setPath(savePath);
+ resource.setUrl(url);
+ resource.setCreatedAt(new Date());
+ resourceService.save(resource);
+
+ return JsonResponse.data(resource);
+ }
+
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 64d9f87..44b19ba 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -41,6 +41,19 @@ spring:
shutdown:
await-termination: true
thread-name-prefix: "playedu-default-thread"
+ # 文件存储配置
+ file-storage:
+ default-platform: "playedu-minio"
+ thumbnail-suffix: ".min.png"
+ minio:
+ - platform: "playedu-minio"
+ enable-storage: true
+ access-key: "username"
+ secret-key: "password"
+ end-point: "http://127.0.0.1:9000"
+ bucket-name: "playedu"
+ domain: "http://127.0.0.1:9000/"
+ base-path: ""
mybatis:
mapper-locations: classpath:mapper/*.xml