diff --git a/.idea/sonarlint/securityhotspotstore/e/6/e6de4bae11e5f329670d8eefa8f2efcb19f7ff88 b/.idea/sonarlint/securityhotspotstore/e/6/e6de4bae11e5f329670d8eefa8f2efcb19f7ff88
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/e/9/e9e9c8aa0ae1931dc6e028fc6aa2a4445d3ba19e b/.idea/sonarlint/securityhotspotstore/e/9/e9e9c8aa0ae1931dc6e028fc6aa2a4445d3ba19e
deleted file mode 100644
index e69de29..0000000
diff --git a/bonus-modules/bonus-obs/pom.xml b/bonus-modules/bonus-obs/pom.xml
new file mode 100644
index 0000000..74ce240
--- /dev/null
+++ b/bonus-modules/bonus-obs/pom.xml
@@ -0,0 +1,103 @@
+
+
+ 4.0.0
+
+ com.bonus
+ bonus-modules
+ 3.6.4
+
+
+ bonus-modules-obs
+
+ bonus-modules-obs存储服务
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-sentinel
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ com.github.tobato
+ fastdfs-client
+
+
+
+
+ io.minio
+ minio
+ ${minio.version}
+
+
+
+
+ com.bonus
+ bonus-api-system
+
+
+
+
+ com.bonus
+ bonus-common-swagger
+
+
+
+ com.huaweicloud
+ esdk-obs-java-bundle
+ 3.23.9
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+
+ ${project.artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/BonusObsApplication.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/BonusObsApplication.java
new file mode 100644
index 0000000..d4b93fd
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/BonusObsApplication.java
@@ -0,0 +1,25 @@
+package com.bonus.obs;
+
+import com.bonus.common.swagger.annotation.EnableCustomSwagger2;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+@EnableCustomSwagger2
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
+public class BonusObsApplication {
+ public static void main(String[] args)
+ {
+ SpringApplication.run(BonusObsApplication.class, args);
+ System.out.println("(♥◠‿◠)ノ゙ obs存储服务模块启动成功 ლ(´ڡ`ლ)゙ \n" +
+ " .-------. ____ __ \n" +
+ " | _ _ \\ \\ \\ / / \n" +
+ " | ( ' ) | \\ _. / ' \n" +
+ " |(_ o _) / _( )_ .' \n" +
+ " | (_,_).' __ ___(_ o _)' \n" +
+ " | |\\ \\ | || |(_,_)' \n" +
+ " | | \\ `' /| `-' / \n" +
+ " | | \\ / \\ / \n" +
+ " ''-' `'-' `-..-' ");
+ }
+}
diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/config/ObsConfig.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/config/ObsConfig.java
new file mode 100644
index 0000000..0867f98
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/config/ObsConfig.java
@@ -0,0 +1,50 @@
+package com.bonus.obs.config;
+
+import com.obs.services.ObsClient;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix = "obs")
+public class ObsConfig {
+
+ private String endpoint;
+ private String ak;
+ private String sk;
+ private String bucket;
+
+
+
+ public String getEndpoint() {
+ return endpoint;
+ }
+
+ public void setEndpoint(String endpoint) {
+ this.endpoint = endpoint;
+ }
+
+ public String getAk() {
+ return ak;
+ }
+
+ public void setAk(String ak) {
+ this.ak = ak;
+ }
+
+ public String getSk() {
+ return sk;
+ }
+
+ public void setSk(String sk) {
+ this.sk = sk;
+ }
+
+ public String getBucket() {
+ return bucket;
+ }
+
+ public void setBucket(String bucket) {
+ this.bucket = bucket;
+ }
+}
diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/controller/ObsController.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/controller/ObsController.java
new file mode 100644
index 0000000..10cafc3
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/controller/ObsController.java
@@ -0,0 +1,90 @@
+package com.bonus.obs.controller;
+
+import com.bonus.common.core.domain.R;
+import com.bonus.obs.service.ObsService;
+import com.bonus.obs.utils.FileUtils;
+import com.obs.services.model.DeleteObjectResult;
+import com.obs.services.model.ObsObject;
+import com.obs.services.model.PutObjectResult;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+@RestController
+@RequestMapping("/obs")
+public class ObsController {
+ @Resource
+ private ObsService service;
+
+ /**
+ * 文件上传
+ *
+ * @param param 文件流
+ * @return 文件信息
+ */
+ @PostMapping("/upload")
+ public R uploadFile(MultipartFile param) {
+ return service.uploadFile(param);
+ }
+
+ /**
+ * 删除文件从OBS
+ *
+ * @param objectKey 文件在OBS中的键
+ */
+ @PostMapping("/delete")
+ public R deleteFile(String objectKey) {
+ return service.deleteFile(objectKey);
+ }
+
+
+ /**
+ * 文件下载
+ *
+ * @param objectKey obs文件存储地址
+ */
+ @GetMapping("/download")
+ public void download(HttpServletResponse response, @RequestParam String objectKey) {
+ R obsObjectR = service.downloadFile(objectKey);
+ try {
+ if (R.isError(obsObjectR)) {
+ response.setStatus(HttpStatus.BAD_REQUEST.value());
+ return;
+ }
+ if (obsObjectR.getData() == null) {
+ response.setStatus(HttpStatus.NOT_FOUND.value());
+ return;
+ }
+ InputStream inputStream = obsObjectR.getData().getObjectContent();
+ String safeFileName = FileUtils.getFileNameFromPath(objectKey);
+ String encodedFileName = URLEncoder.encode(safeFileName, StandardCharsets.UTF_8.toString());
+ response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
+ response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"");
+ try (OutputStream outputStream = response.getOutputStream()) {
+ byte[] buffer = new byte[8192];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ outputStream.flush();
+ } catch (IOException e) {
+ response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ }
+ } catch (IllegalArgumentException e) {
+ response.setStatus(HttpStatus.BAD_REQUEST.value());
+ } catch (Exception e) {
+ response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ }
+ }
+
+}
diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/domain/ObsInfo.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/domain/ObsInfo.java
new file mode 100644
index 0000000..4253fb8
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/domain/ObsInfo.java
@@ -0,0 +1,42 @@
+package com.bonus.obs.domain;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * OBS(Object Storage Service)信息类。
+ * 用于封装与OBS对象相关的元数据信息。
+ */
+@Data
+@Builder
+public class ObsInfo {
+ /**
+ * 对象的名称。
+ * 代表OBS对象的唯一标识。
+ */
+ private String name;
+
+ /**
+ * 对象在OBS中的存储路径。
+ * 包含桶(bucket)名称和对象在桶内的相对路径。
+ */
+ private String path;
+
+ /**
+ * 对象的大小。
+ * 以字符串形式表示,可能包含单位(如字节、KB、MB等)。
+ */
+ private String length;
+
+ /**
+ * 对象的文件类型。
+ * 用于标识对象的MIME类型,例如text/plain、image/jpeg等。
+ */
+ private String fileType;
+
+ /**
+ * 对象所属的桶(bucket)的名称。
+ * 每个桶在OBS中都是唯一的,用于存储对象。
+ */
+ private String bucketName;
+}
diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/ObsService.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/ObsService.java
new file mode 100644
index 0000000..c9c64ce
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/ObsService.java
@@ -0,0 +1,31 @@
+package com.bonus.obs.service;
+
+import com.bonus.common.core.domain.R;
+import com.obs.services.model.DeleteObjectResult;
+import com.obs.services.model.ObsObject;
+import com.obs.services.model.PutObjectResult;
+import org.springframework.web.multipart.MultipartFile;
+
+public interface ObsService {
+ /**
+ * 文件上传
+ *
+ * @param param 文件流
+ * @return 文件信息
+ */
+ R uploadFile(MultipartFile param);
+
+ /**
+ * 删除文件从OBS
+ *
+ * @param objectKey 文件在OBS中的键
+ */
+ public R deleteFile(String objectKey);
+
+ /**
+ * 下载文件从OBS
+ *
+ * @param objectKey 文件在OBS中的键
+ */
+ public R downloadFile(String objectKey);
+}
diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/impl/ObsServiceImpl.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/impl/ObsServiceImpl.java
new file mode 100644
index 0000000..8042338
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/impl/ObsServiceImpl.java
@@ -0,0 +1,58 @@
+package com.bonus.obs.service.impl;
+
+import com.bonus.common.core.domain.R;
+import com.bonus.obs.service.ObsService;
+import com.bonus.obs.utils.FileUtils;
+import com.bonus.obs.utils.ObsUtils;
+import com.obs.services.model.DeleteObjectResult;
+import com.obs.services.model.ObsObject;
+import com.obs.services.model.PutObjectResult;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.io.File;
+
+@Service
+public class ObsServiceImpl implements ObsService {
+ @Resource
+ private ObsUtils obsUtils;
+
+ /**
+ * 文件上传
+ *
+ * @param param 文件流
+ * @return 文件信息
+ */
+ @Override
+ public R uploadFile(MultipartFile param) {
+ try {
+ String objectKey = param.getOriginalFilename();
+ File file = FileUtils.multipartFileToFile(param);
+ objectKey = FileUtils.generateObjectName(objectKey);
+ return obsUtils.uploadFile(objectKey, file);
+ } catch (Exception e) {
+ return R.fail(e.getMessage());
+ }
+ }
+
+ /**
+ * 删除文件从OBS
+ *
+ * @param objectKey 文件在OBS中的键
+ */
+ @Override
+ public R deleteFile(String objectKey) {
+ return obsUtils.deleteFile(objectKey);
+ }
+
+ /**
+ * 下载文件从OBS
+ *
+ * @param objectKey 文件在OBS中的键
+ */
+ @Override
+ public R downloadFile(String objectKey) {
+ return obsUtils.downloadFile(objectKey);
+ }
+}
diff --git a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/utils/FileUtils.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/utils/FileUtils.java
similarity index 98%
rename from bonus-modules/bonus-oss/src/main/java/com/bonus/oss/utils/FileUtils.java
rename to bonus-modules/bonus-obs/src/main/java/com/bonus/obs/utils/FileUtils.java
index 61c379f..c40d5d0 100644
--- a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/utils/FileUtils.java
+++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/utils/FileUtils.java
@@ -1,4 +1,4 @@
-package com.bonus.oss.utils;
+package com.bonus.obs.utils;
import com.bonus.common.core.utils.StringUtils;
import org.springframework.web.multipart.MultipartFile;
diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/utils/ObsUtils.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/utils/ObsUtils.java
new file mode 100644
index 0000000..f54e772
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/utils/ObsUtils.java
@@ -0,0 +1,87 @@
+package com.bonus.obs.utils;
+
+import com.bonus.common.core.domain.R;
+import com.bonus.obs.config.ObsConfig;
+import com.obs.services.ObsClient;
+import com.obs.services.model.DeleteObjectResult;
+import com.obs.services.model.GetObjectRequest;
+import com.obs.services.model.ObsObject;
+import com.obs.services.model.PutObjectResult;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+@Service
+public class ObsUtils {
+
+ @Resource
+ private ObsConfig obsConfig;
+ /**
+ * obs 客户端
+ */
+ private ObsClient obsClient;
+
+ /**
+ * 初始化信息
+ * 构建OSS客户端实例
+ */
+ @PostConstruct
+ public void init() {
+ obsClient = new ObsClient(obsConfig.getAk(), obsConfig.getSk(), obsConfig.getEndpoint());
+ }
+
+
+ /**
+ * 上传文件到OBS
+ *
+ * @param file 要上传的文件
+ * @return 上传结果
+ */
+ public R uploadFile(String objectKey, File file) {
+ return R.ok(obsClient.putObject(obsConfig.getBucket(), objectKey, file));
+ }
+
+ /**
+ * 下载文件从OBS
+ *
+ * @param objectKey 文件在OBS中的键
+ */
+ public R downloadFile(String objectKey) {
+ if (!doesObjectExist(objectKey)) {
+ return R.fail("文件不存在");
+ }
+ return R.ok(obsClient.getObject(new GetObjectRequest(obsConfig.getBucket(), objectKey)));
+ }
+
+ /**
+ * 删除文件从OBS
+ *
+ * @param objectKey 文件在OBS中的键
+ */
+ public R deleteFile(String objectKey) {
+ if (!doesObjectExist(objectKey)) {
+ return R.fail("文件不存在");
+ }
+ return R.ok(obsClient.deleteObject(obsConfig.getBucket(), objectKey));
+ }
+
+ /**
+ * 判断文件是否存在
+ *
+ * @param objectKey 文件在OBS中的键
+ * @return 如果文件存在则返回true,否则返回false
+ */
+ public boolean doesObjectExist(String objectKey) {
+ try {
+ return obsClient.doesObjectExist(obsConfig.getBucket(), objectKey);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+}
diff --git a/bonus-modules/bonus-obs/src/main/resources/banner.txt b/bonus-modules/bonus-obs/src/main/resources/banner.txt
new file mode 100644
index 0000000..7046037
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/resources/banner.txt
@@ -0,0 +1,9 @@
+Spring Boot Version: ${spring-boot.version}
+Spring Application Name: ${spring.application.name}
+ _ _
+ | | | |
+ | |__ ___ _ __ _ _ ___ ______ ___ | |__ ___
+ | '_ \ / _ \ | '_ \ | | | | / __| |______| / _ \ | '_ \ / __|
+ | |_) | | (_) | | | | | | |_| | \__ \ | (_) | | |_) | \__ \
+ |_.__/ \___/ |_| |_| \__,_| |___/ \___/ |_.__/ |___/
+
diff --git a/bonus-modules/bonus-obs/src/main/resources/bootstrap.yml b/bonus-modules/bonus-obs/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..333abac
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/resources/bootstrap.yml
@@ -0,0 +1,29 @@
+# Tomcat
+server:
+ port: 9205
+
+# Spring
+spring:
+ application:
+ # 应用名称
+ name: bonus-obs
+ profiles:
+ # 环境配置
+ active: dev
+ cloud:
+ nacos:
+ username: nacos
+ password: nacos
+ discovery:
+ # 服务注册地址
+ server-addr: 192.168.0.14:8848
+ namespace: f1fcd3ea-9460-4597-8acd-0f334527017c
+ config:
+ # 配置中心地址
+ server-addr: 192.168.0.14:8848
+ namespace: f1fcd3ea-9460-4597-8acd-0f334527017c
+ # 配置文件格式
+ file-extension: yml
+ # 共享配置
+ shared-configs:
+ - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
diff --git a/bonus-modules/bonus-obs/src/main/resources/logback.xml b/bonus-modules/bonus-obs/src/main/resources/logback.xml
new file mode 100644
index 0000000..7607fdf
--- /dev/null
+++ b/bonus-modules/bonus-obs/src/main/resources/logback.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+ ${log.pattern}
+
+
+
+
+
+ ${log.path}/info.log
+
+
+
+ ${log.path}/info.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ INFO
+
+ ACCEPT
+
+ DENY
+
+
+
+
+ ${log.path}/error.log
+
+
+
+ ${log.path}/error.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ ERROR
+
+ ACCEPT
+
+ DENY
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file