diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java
index df84836c..97440057 100644
--- a/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java
+++ b/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java
@@ -24,7 +24,6 @@ import me.zhengjie.exception.BadRequestException;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.springframework.web.multipart.MultipartFile;
-
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -136,15 +135,15 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
String resultSize;
if (size / GB >= 1) {
//如果当前Byte的值大于等于1GB
- resultSize = DF.format(size / (float) GB) + "GB ";
+ resultSize = DF.format(size / (float) GB) + "GB";
} else if (size / MB >= 1) {
//如果当前Byte的值大于等于1MB
- resultSize = DF.format(size / (float) MB) + "MB ";
+ resultSize = DF.format(size / (float) MB) + "MB";
} else if (size / KB >= 1) {
//如果当前Byte的值大于等于1KB
- resultSize = DF.format(size / (float) KB) + "KB ";
+ resultSize = DF.format(size / (float) KB) + "KB";
} else {
- resultSize = size + "B ";
+ resultSize = size + "B";
}
return resultSize;
}
diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/RedisUtils.java b/eladmin-common/src/main/java/me/zhengjie/utils/RedisUtils.java
index 21480065..806431cc 100644
--- a/eladmin-common/src/main/java/me/zhengjie/utils/RedisUtils.java
+++ b/eladmin-common/src/main/java/me/zhengjie/utils/RedisUtils.java
@@ -16,6 +16,7 @@
package me.zhengjie.utils;
import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
@@ -234,7 +235,10 @@ public class RedisUtils {
if (value == null) {
return null;
}
- if (clazz.isInstance(value)) {
+ // 如果 value 不是目标类型,则尝试将其反序列化为 clazz 类型
+ if (!clazz.isInstance(value)) {
+ return JSON.parseObject(value.toString(), clazz);
+ } else if (clazz.isInstance(value)) {
return clazz.cast(value);
} else {
return null;
diff --git a/eladmin-logging/src/main/java/me/zhengjie/service/impl/SysLogServiceImpl.java b/eladmin-logging/src/main/java/me/zhengjie/service/impl/SysLogServiceImpl.java
index bcff3710..455f7b86 100644
--- a/eladmin-logging/src/main/java/me/zhengjie/service/impl/SysLogServiceImpl.java
+++ b/eladmin-logging/src/main/java/me/zhengjie/service/impl/SysLogServiceImpl.java
@@ -18,6 +18,7 @@ package me.zhengjie.service.impl;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import me.zhengjie.domain.SysLog;
@@ -136,7 +137,14 @@ public class SysLogServiceImpl implements SysLogService {
// 将RequestBody注解修饰的参数作为请求参数
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
if (requestBody != null) {
- params.putAll((JSONObject) JSON.toJSON(args[i]));
+ // [el-async-1] ERROR o.s.a.i.SimpleAsyncUncaughtExceptionHandler - Unexpected exception occurred invoking async method: public void me.zhengjie.service.impl.SysLogServiceImpl.save(java.lang.String,java.lang.String,java.lang.String,org.aspectj.lang.ProceedingJoinPoint,me.zhengjie.domain.SysLog)
+ // java.lang.ClassCastException: com.alibaba.fastjson2.JSONArray cannot be cast to com.alibaba.fastjson2.JSONObject
+ Object json = JSON.toJSON(args[i]);
+ if (json instanceof JSONArray) {
+ params.put("reqBodyList", json);
+ } else {
+ params.putAll((JSONObject) json);
+ }
} else {
String key = parameters[i].getName();
params.put(key, args[i]);
diff --git a/eladmin-system/src/main/java/me/zhengjie/AppRun.java b/eladmin-system/src/main/java/me/zhengjie/AppRun.java
index a8dfb89a..696b1520 100644
--- a/eladmin-system/src/main/java/me/zhengjie/AppRun.java
+++ b/eladmin-system/src/main/java/me/zhengjie/AppRun.java
@@ -22,6 +22,7 @@ import me.zhengjie.utils.SpringBeanHolder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.ApplicationPidFileWriter;
+import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.http.HttpStatus;
@@ -50,10 +51,11 @@ public class AppRun {
// 监控应用的PID,启动时可指定PID路径:--spring.pid.file=/home/eladmin/app.pid
// 或者在 application.yml 添加文件路径,方便 kill,kill `cat /home/eladmin/app.pid`
springApplication.addListeners(new ApplicationPidFileWriter());
- springApplication.run(args);
+ ConfigurableApplicationContext context = springApplication.run(args);
+ String port = context.getEnvironment().getProperty("server.port");
log.info("---------------------------------------------");
- log.info("Local: {}", "http://localhost:8000");
- log.info("Swagger: {}", "http://localhost:8000/doc.html");
+ log.info("Local: http://localhost:{}", port);
+ log.info("Swagger: http://localhost:{}/doc.html", port);
log.info("---------------------------------------------");
}
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/AppServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/AppServiceImpl.java
index d7aeb296..9fee6182 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/AppServiceImpl.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/AppServiceImpl.java
@@ -56,7 +56,7 @@ public class AppServiceImpl implements AppService {
@Override
public AppDto findById(Long id) {
- App app = appRepository.findById(id).orElseGet(App::new);
+ App app = appRepository.findById(id).orElseGet(App::new);
ValidationUtil.isNull(app.getId(),"App","id",id);
return appMapper.toDto(app);
}
@@ -64,6 +64,11 @@ public class AppServiceImpl implements AppService {
@Override
@Transactional(rollbackFor = Exception.class)
public void create(App resources) {
+ // 验证应用名称是否存在恶意攻击payload,https://github.com/elunez/eladmin/issues/873
+ String appName = resources.getName();
+ if (appName.contains(";") || appName.contains("|") || appName.contains("&")) {
+ throw new IllegalArgumentException("非法的应用名称,请勿包含[; | &]等特殊字符");
+ }
verification(resources);
appRepository.save(resources);
}
@@ -71,6 +76,11 @@ public class AppServiceImpl implements AppService {
@Override
@Transactional(rollbackFor = Exception.class)
public void update(App resources) {
+ // 验证应用名称是否存在恶意攻击payload,https://github.com/elunez/eladmin/issues/873
+ String appName = resources.getName();
+ if (appName.contains(";") || appName.contains("|") || appName.contains("&")) {
+ throw new IllegalArgumentException("非法的应用名称,请勿包含[; | &]等特殊字符");
+ }
verification(resources);
App app = appRepository.findById(resources.getId()).orElseGet(App::new);
ValidationUtil.isNull(app.getId(),"App","id",resources.getId());
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/DeployServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/DeployServiceImpl.java
index 41a25988..350cff2e 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/DeployServiceImpl.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/DeployServiceImpl.java
@@ -263,9 +263,13 @@ public class DeployServiceImpl implements DeployService {
return "执行完毕";
}
- private boolean checkFile(ExecuteShellUtil executeShellUtil, AppDto appDTO) {
- String result = executeShellUtil.executeForResult("find " + appDTO.getDeployPath() + " -name " + appDTO.getName());
- return result.indexOf(appDTO.getName())>0;
+ private boolean checkFile(ExecuteShellUtil executeShellUtil, AppDto app) {
+ String deployPath = app.getDeployPath();
+ String appName = app.getName();
+ // 使用安全的命令执行方式,避免直接拼接字符串,https://github.com/elunez/eladmin/issues/873
+ String[] command = {"find", deployPath, "-name", appName};
+ String result = executeShellUtil.executeForResult(Arrays.toString(command));
+ return result.contains(appName);
}
/**
diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java
index 73659ca0..e1eb0c0e 100644
--- a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java
+++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java
@@ -42,8 +42,8 @@ import java.util.concurrent.TimeUnit;
@Component
public class TokenProvider implements InitializingBean {
+ private Key signingKey;
private JwtParser jwtParser;
- private JwtBuilder jwtBuilder;
private final RedisUtils redisUtils;
private final SecurityProperties properties;
public static final String AUTHORITIES_UUID_KEY = "uid";
@@ -56,13 +56,13 @@ public class TokenProvider implements InitializingBean {
@Override
public void afterPropertiesSet() {
+ // 解码Base64密钥并创建签名密钥
byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret());
- Key key = Keys.hmacShaKeyFor(keyBytes);
+ this.signingKey = Keys.hmacShaKeyFor(keyBytes);
+ // 初始化 JwtParser
jwtParser = Jwts.parserBuilder()
- .setSigningKey(key)
+ .setSigningKey(signingKey) // 使用预生成的签名密钥
.build();
- jwtBuilder = Jwts.builder()
- .signWith(key, SignatureAlgorithm.HS512);
}
/**
@@ -79,9 +79,14 @@ public class TokenProvider implements InitializingBean {
claims.put(AUTHORITIES_UID_KEY, user.getUser().getId());
// 设置UUID,确保每次Token不一样
claims.put(AUTHORITIES_UUID_KEY, IdUtil.simpleUUID());
- return jwtBuilder
+ // 直接调用 Jwts.builder() 创建新实例
+ return Jwts.builder()
+ // 设置自定义 Claims
.setClaims(claims)
+ // 设置主题
.setSubject(user.getUsername())
+ // 使用预生成的签名密钥和算法签名
+ .signWith(signingKey, SignatureAlgorithm.HS512)
.compact();
}
diff --git a/eladmin-system/src/main/resources/config/application-dev.yml b/eladmin-system/src/main/resources/config/application-dev.yml
index 1707a6ac..f9939136 100644
--- a/eladmin-system/src/main/resources/config/application-dev.yml
+++ b/eladmin-system/src/main/resources/config/application-dev.yml
@@ -116,3 +116,22 @@ file:
# 文件大小 /M
maxSize: 1
avatarMaxSize: 5
+
+# 亚马逊S3协议云存储配置
+#支持七牛云,阿里云OSS,腾讯云COS,华为云OBS,移动云EOS等
+amz:
+ s3:
+ # 地域
+ region: test
+ # 地域对应的 endpoint
+ endPoint: https://s3.test.com
+ # 访问的域名
+ domain: https://s3.test.com
+ # 账号的认证信息,或者子账号的认证信息
+ accessKey: 填写你的AccessKey
+ secretKey: 填写你的SecretKey
+ # 存储桶(Bucket)
+ defaultBucket: 填写你的存储桶名称
+ # 文件存储路径
+ timeformat: yyyy-MM
+
diff --git a/eladmin-system/src/main/resources/config/application-prod.yml b/eladmin-system/src/main/resources/config/application-prod.yml
index 421d0358..8f7f615e 100644
--- a/eladmin-system/src/main/resources/config/application-prod.yml
+++ b/eladmin-system/src/main/resources/config/application-prod.yml
@@ -127,3 +127,21 @@ file:
# 文件大小 /M
maxSize: 1
avatarMaxSize: 5
+
+# 亚马逊S3协议云存储配置
+#支持七牛云,阿里云OSS,腾讯云COS,华为云OBS,移动云EOS等
+amz:
+ s3:
+ # 地域
+ region: test
+ # 地域对应的 endpoint
+ endPoint: https://s3.test.com
+ # 访问的域名
+ domain: https://s3.test.com
+ # 账号的认证信息,或者子账号的认证信息
+ accessKey: 填写你的AccessKey
+ secretKey: 填写你的SecretKey
+ # 存储桶(Bucket)
+ defaultBucket: 填写你的存储桶名称
+ # 文件存储路径
+ timeformat: yyyy-MM
\ No newline at end of file
diff --git a/eladmin-system/src/main/resources/config/application.yml b/eladmin-system/src/main/resources/config/application.yml
index a428714e..f4dfc039 100644
--- a/eladmin-system/src/main/resources/config/application.yml
+++ b/eladmin-system/src/main/resources/config/application.yml
@@ -65,11 +65,6 @@ task:
# 队列容量
queue-capacity: 30
-#七牛云
-qiniu:
- # 文件大小 /M
- max-size: 1
-
#邮箱验证码有效时间/秒
code:
expiration: 300
diff --git a/eladmin-tools/pom.xml b/eladmin-tools/pom.xml
index 24cd54cd..cde0be3a 100644
--- a/eladmin-tools/pom.xml
+++ b/eladmin-tools/pom.xml
@@ -44,5 +44,13 @@
alipay-sdk-java
${alipay.version}
+
+
+
+ software.amazon.awssdk
+ s3
+ 2.30.13
+ compile
+
diff --git a/eladmin-tools/src/main/java/me/zhengjie/config/AmzS3Config.java b/eladmin-tools/src/main/java/me/zhengjie/config/AmzS3Config.java
new file mode 100644
index 00000000..fcf952a8
--- /dev/null
+++ b/eladmin-tools/src/main/java/me/zhengjie/config/AmzS3Config.java
@@ -0,0 +1,78 @@
+package me.zhengjie.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import java.net.URI;
+
+/**
+ * @author Zheng Jie
+ * @date 2025-06-25
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "amz.s3")
+public class AmzS3Config {
+
+ /**
+ * Amazon S3 的区域配置,例如 "us-west-2"。
+ * 该区域决定了 S3 存储桶的地理位置。
+ */
+ private String region;
+
+ /**
+ * Amazon S3 的端点 URL
+ * 该端点用于访问 S3 服务。
+ */
+ private String endPoint;
+
+ /**
+ * Amazon S3 的域名
+ * 该域名用于构建访问 S3 服务的完整 URL。
+ */
+ private String domain;
+
+ /**
+ * Amazon S3 的访问密钥 ID,用于身份验证。
+ * 该密钥与 secretKey 一起使用来授权对 S3 服务的访问。
+ */
+ private String accessKey;
+
+ /**
+ * Amazon S3 的秘密访问密钥,用于身份验证。
+ * 该密钥与 accessKey 一起使用来授权对 S3 服务的访问。
+ */
+ private String secretKey;
+
+ /**
+ * 默认的 S3 存储桶名称。
+ * 该存储桶用于存储上传的文件和数据。
+ */
+ private String defaultBucket;
+
+ /**
+ * 文件上传后存储的文件夹格式,默认为 "yyyy-MM"。
+ */
+ private String timeformat;
+
+ /**
+ * 创建并返回一个 AmazonS3 客户端实例。
+ * 使用当前配置类的 endPoint, region, accessKey 和 secretKey。
+ * 声明为 @Bean 后,Spring 会将其作为单例管理,并在需要时自动注入。
+ *
+ * @return 配置好的 AmazonS3 客户端实例
+ */
+ @Bean
+ public S3Client amazonS3Client() {
+ return S3Client.builder().region(Region.of(region))
+ .endpointOverride(URI.create(endPoint))
+ .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey)))
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/eladmin-tools/src/main/java/me/zhengjie/domain/QiniuConfig.java b/eladmin-tools/src/main/java/me/zhengjie/domain/QiniuConfig.java
deleted file mode 100644
index f9140b1d..00000000
--- a/eladmin-tools/src/main/java/me/zhengjie/domain/QiniuConfig.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2019-2025 Zheng Jie
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package me.zhengjie.domain;
-
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import javax.persistence.*;
-import javax.validation.constraints.NotBlank;
-import java.io.Serializable;
-
-/**
- * 七牛云对象存储配置类
- * @author Zheng Jie
- * @date 2018-12-31
- */
-@Data
-@Entity
-@Table(name = "tool_qiniu_config")
-public class QiniuConfig implements Serializable {
-
- @Id
- @Column(name = "config_id")
- @ApiModelProperty(value = "ID")
- private Long id;
-
- @NotBlank
- @ApiModelProperty(value = "accessKey")
- private String accessKey;
-
- @NotBlank
- @ApiModelProperty(value = "secretKey")
- private String secretKey;
-
- @NotBlank
- @ApiModelProperty(value = "存储空间名称作为唯一的 Bucket 识别符")
- private String bucket;
-
- /**
- * Zone表示与机房的对应关系
- * 华东 Zone.zone0()
- * 华北 Zone.zone1()
- * 华南 Zone.zone2()
- * 北美 Zone.zoneNa0()
- * 东南亚 Zone.zoneAs0()
- */
- @NotBlank
- @ApiModelProperty(value = "Zone表示与机房的对应关系")
- private String zone;
-
- @NotBlank
- @ApiModelProperty(value = "外链域名,可自定义,需在七牛云绑定")
- private String host;
-
- @ApiModelProperty(value = "空间类型:公开/私有")
- private String type = "公开";
-}
diff --git a/eladmin-tools/src/main/java/me/zhengjie/domain/QiniuContent.java b/eladmin-tools/src/main/java/me/zhengjie/domain/QiniuContent.java
deleted file mode 100644
index b7511db0..00000000
--- a/eladmin-tools/src/main/java/me/zhengjie/domain/QiniuContent.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2019-2025 Zheng Jie
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package me.zhengjie.domain;
-
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.hibernate.annotations.UpdateTimestamp;
-import javax.persistence.*;
-import java.io.Serializable;
-import java.sql.Timestamp;
-
-/**
- * 上传成功后,存储结果
- * @author Zheng Jie
- * @date 2018-12-31
- */
-@Data
-@Entity
-@Table(name = "tool_qiniu_content")
-public class QiniuContent implements Serializable {
-
- @Id
- @Column(name = "content_id")
- @ApiModelProperty(value = "ID", hidden = true)
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- @Column(name = "name")
- @ApiModelProperty(value = "文件名")
- private String key;
-
- @ApiModelProperty(value = "空间名")
- private String bucket;
-
- @ApiModelProperty(value = "大小")
- private String size;
-
- @ApiModelProperty(value = "文件地址")
- private String url;
-
- @ApiModelProperty(value = "文件类型")
- private String suffix;
-
- @ApiModelProperty(value = "空间类型:公开/私有")
- private String type = "公开";
-
- @UpdateTimestamp
- @ApiModelProperty(value = "创建或更新时间")
- @Column(name = "update_time")
- private Timestamp updateTime;
-}
diff --git a/eladmin-tools/src/main/java/me/zhengjie/domain/S3Storage.java b/eladmin-tools/src/main/java/me/zhengjie/domain/S3Storage.java
new file mode 100644
index 00000000..389f6273
--- /dev/null
+++ b/eladmin-tools/src/main/java/me/zhengjie/domain/S3Storage.java
@@ -0,0 +1,72 @@
+/*
+* Copyright 2019-2025 Zheng Jie
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package me.zhengjie.domain;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import me.zhengjie.base.BaseEntity;
+import javax.persistence.*;
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+* @description S3存储实体类
+* @author Zheng Jie
+* @date 2025-06-25
+**/
+@Data
+@Entity
+@Table(name = "tool_s3_storage")
+@EqualsAndHashCode(callSuper = true)
+public class S3Storage extends BaseEntity implements Serializable {
+
+ @Id
+ @Column(name = "storage_id")
+ @ApiModelProperty(value = "ID", hidden = true)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @NotBlank
+ @ApiModelProperty(value = "文件名称")
+ private String fileName;
+
+ @NotBlank
+ @ApiModelProperty(value = "真实存储的名称")
+ private String fileRealName;
+
+ @NotBlank
+ @ApiModelProperty(value = "文件大小")
+ private String fileSize;
+
+ @NotBlank
+ @ApiModelProperty(value = "文件MIME 类型")
+ private String fileMimeType;
+
+ @NotBlank
+ @ApiModelProperty(value = "文件类型")
+ private String fileType;
+
+ @NotBlank
+ @ApiModelProperty(value = "文件路径")
+ private String filePath;
+
+ public void copy(S3Storage source){
+ BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
+ }
+}
diff --git a/eladmin-tools/src/main/java/me/zhengjie/repository/QiNiuConfigRepository.java b/eladmin-tools/src/main/java/me/zhengjie/repository/QiNiuConfigRepository.java
deleted file mode 100644
index eb9045a8..00000000
--- a/eladmin-tools/src/main/java/me/zhengjie/repository/QiNiuConfigRepository.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2019-2025 Zheng Jie
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package me.zhengjie.repository;
-
-import me.zhengjie.domain.QiniuConfig;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-
-/**
- * @author Zheng Jie
- * @date 2018-12-31
- */
-public interface QiNiuConfigRepository extends JpaRepository {
-
- /**
- * 编辑类型
- * @param type /
- */
- @Modifying
- @Query(value = "update QiniuConfig set type = ?1")
- void update(String type);
-}
diff --git a/eladmin-tools/src/main/java/me/zhengjie/repository/QiniuContentRepository.java b/eladmin-tools/src/main/java/me/zhengjie/repository/S3StorageRepository.java
similarity index 62%
rename from eladmin-tools/src/main/java/me/zhengjie/repository/QiniuContentRepository.java
rename to eladmin-tools/src/main/java/me/zhengjie/repository/S3StorageRepository.java
index 10b0e157..9ad9f2a8 100644
--- a/eladmin-tools/src/main/java/me/zhengjie/repository/QiniuContentRepository.java
+++ b/eladmin-tools/src/main/java/me/zhengjie/repository/S3StorageRepository.java
@@ -15,20 +15,22 @@
*/
package me.zhengjie.repository;
-import me.zhengjie.domain.QiniuContent;
+import me.zhengjie.domain.S3Storage;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
/**
- * @author Zheng Jie
- * @date 2018-12-31
- */
-public interface QiniuContentRepository extends JpaRepository, JpaSpecificationExecutor {
+* @author Zheng Jie
+* @date 2025-06-25
+*/
+public interface S3StorageRepository extends JpaRepository, JpaSpecificationExecutor {
- /**
- * 根据key查询
- * @param key 文件名
- * @return QiniuContent
- */
- QiniuContent findByKey(String key);
-}
+ /**
+ * 根据ID查询文件路径
+ * @param id 文件ID
+ * @return 文件路径
+ */
+ @Query(value = "SELECT file_path FROM s3_storage WHERE id = ?1", nativeQuery = true)
+ String selectFilePathById(Long id);
+}
\ No newline at end of file
diff --git a/eladmin-tools/src/main/java/me/zhengjie/rest/QiniuController.java b/eladmin-tools/src/main/java/me/zhengjie/rest/QiniuController.java
deleted file mode 100644
index f17ce3bb..00000000
--- a/eladmin-tools/src/main/java/me/zhengjie/rest/QiniuController.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2019-2025 Zheng Jie
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package me.zhengjie.rest;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import me.zhengjie.annotation.Log;
-import me.zhengjie.domain.QiniuConfig;
-import me.zhengjie.domain.QiniuContent;
-import me.zhengjie.service.dto.QiniuQueryCriteria;
-import me.zhengjie.service.QiNiuService;
-import me.zhengjie.utils.PageResult;
-import org.springframework.data.domain.Pageable;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 发送邮件
- * @author 郑杰
- * @date 2018/09/28 6:55:53
- */
-@Slf4j
-@RestController
-@RequiredArgsConstructor
-@RequestMapping("/api/qiNiuContent")
-@Api(tags = "工具:七牛云存储管理")
-public class QiniuController {
-
- private final QiNiuService qiNiuService;
-
- @GetMapping(value = "/config")
- public ResponseEntity queryQiNiuConfig(){
- return new ResponseEntity<>(qiNiuService.find(), HttpStatus.OK);
- }
-
- @Log("配置七牛云存储")
- @ApiOperation("配置七牛云存储")
- @PutMapping(value = "/config")
- public ResponseEntity