feat(infra): 文件存储支持相对路径

- 在 DB、FTP、Local、S3 和 SFTP 文件客户端中添加相对路径支持
- 新增 useRelativePath 和 relativePathPrefix 配置项
- 修改文件 URL 格式化逻辑,支持相对路径和自定义域名- 更新文件配置 DO,将支付渠道配置改为文件存储客户端配置
This commit is contained in:
王祁 2025-05-15 12:57:47 +08:00
parent 23bb3ebd23
commit a7c10d8d41
11 changed files with 69 additions and 13 deletions

View File

@ -62,7 +62,7 @@ public class FileConfigDO extends BaseDO {
private Boolean master;
/**
* 支付渠道配置
* 文件存储客户端配置
*/
@TableField(typeHandler = FileClientConfigTypeHandler.class)
private FileClientConfig config;

View File

@ -33,6 +33,10 @@ public class DBFileClient extends AbstractFileClient<DBFileClientConfig> {
.setPath(path).setContent(content);
fileContentMapper.insert(contentDO);
// 拼接返回路径
if (config.getUseRelativePath()){
// 如果是 相对路径则拼接相对路径前缀
return super.formatFileUrl(config.getRelativePathPrefix(), path);
}
return super.formatFileUrl(config.getDomain(), path);
}

View File

@ -1,10 +1,8 @@
package cn.iocoder.yudao.module.infra.framework.file.core.client.db;
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
import jakarta.validation.constraints.NotEmpty;
/**
* 基于 DB 存储的文件客户端的配置类
@ -14,11 +12,18 @@ import jakarta.validation.constraints.NotEmpty;
@Data
public class DBFileClientConfig implements FileClientConfig {
@NotNull(message = "是否使用相对路径不能为空")
private Boolean useRelativePath = false;
private String relativePathPrefix = "/file";
/**
* 自定义域名
*/
@NotEmpty(message = "domain 不能为空")
@URL(message = "domain 必须是 URL 格式")
// TODO 王祁 20250515 这里看如何做校验当useRelativePath为true时只校验relativePath否则只校验domain还是说在前端做
// @NotEmpty(message = "domain 不能为空")
// @URL(message = "domain 必须是 URL 格式")
private String domain;
}

View File

@ -43,6 +43,10 @@ public class FtpFileClient extends AbstractFileClient<FtpFileClientConfig> {
throw new FtpException(StrUtil.format("上传文件到目标目录 ({}) 失败", filePath));
}
// 拼接返回路径
if (config.getUseRelativePath()){
// 如果是 相对路径则拼接相对路径前缀
return super.formatFileUrl(config.getRelativePathPrefix(), path);
}
return super.formatFileUrl(config.getDomain(), path);
}

View File

@ -21,11 +21,18 @@ public class FtpFileClientConfig implements FileClientConfig {
@NotEmpty(message = "基础路径不能为空")
private String basePath;
@NotNull(message = "是否使用相对路径不能为空")
private Boolean useRelativePath = false;
private String relativePathPrefix = "/file";
/**
* 自定义域名
*/
@NotEmpty(message = "domain 不能为空")
@URL(message = "domain 必须是 URL 格式")
// TODO 王祁 20250515 这里看如何做校验当useRelativePath为true时只校验relativePath否则只校验domain还是说在前端做
// @NotEmpty(message = "domain 不能为空")
// @URL(message = "domain 必须是 URL 格式")
private String domain;
/**

View File

@ -26,6 +26,10 @@ public class LocalFileClient extends AbstractFileClient<LocalFileClientConfig> {
String filePath = getFilePath(path);
FileUtil.writeBytes(content, filePath);
// 拼接返回路径
if (config.getUseRelativePath()){
// 如果是 相对路径则拼接相对路径前缀
return super.formatFileUrl(config.getRelativePathPrefix(), path);
}
return super.formatFileUrl(config.getDomain(), path);
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.infra.framework.file.core.client.local;
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
@ -20,11 +21,18 @@ public class LocalFileClientConfig implements FileClientConfig {
@NotEmpty(message = "基础路径不能为空")
private String basePath;
@NotNull(message = "是否使用相对路径不能为空")
private Boolean useRelativePath = false;
private String relativePathPrefix = "/file";
/**
* 自定义域名
*/
@NotEmpty(message = "domain 不能为空")
@URL(message = "domain 必须是 URL 格式")
// TODO 王祁 20250515 这里看如何做校验当useRelativePath为true时只校验relativePath否则只校验domain还是说在前端做
// @NotEmpty(message = "domain 不能为空")
// @URL(message = "domain 必须是 URL 格式")
private String domain;
}

View File

@ -75,6 +75,10 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
// 上传文件
client.putObject(putRequest, RequestBody.fromBytes(content));
// 拼接返回路径
if (config.getUseRelativePath()){
// 如果是 相对路径则拼接相对路径前缀
return config.getRelativePathPrefix() + "/" + path;
}
return config.getDomain() + "/" + path;
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.framework.file.core.client.s3;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClientConfig;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
@ -33,6 +34,13 @@ public class S3FileClientConfig implements FileClientConfig {
*/
@NotNull(message = "endpoint 不能为空")
private String endpoint;
@NotNull(message = "是否使用相对路径不能为空")
private Boolean useRelativePath = false;
private String relativePathPrefix = "/file";
/**
* 自定义域名
* 1. MinIO通过 Nginx 配置
@ -42,7 +50,9 @@ public class S3FileClientConfig implements FileClientConfig {
* 5. 华为云https://support.huaweicloud.com/usermanual-obs/obs_03_0032.html
* 6. 火山云https://www.volcengine.com/docs/6349/128983
*/
@URL(message = "domain 必须是 URL 格式")
// TODO 王祁 20250515 这里看如何做校验当useRelativePath为true时只校验relativePath否则只校验domain还是说在前端做
// @NotEmpty(message = "domain 不能为空")
// @URL(message = "domain 必须是 URL 格式")
private String domain;
/**
* 存储 Bucket

View File

@ -35,6 +35,10 @@ public class SftpFileClient extends AbstractFileClient<SftpFileClientConfig> {
sftp.mkDirs(FileUtil.getParent(filePath, 1)); // 需要创建父目录不然会报错
sftp.upload(filePath, file);
// 拼接返回路径
if (config.getUseRelativePath()){
// 如果是 相对路径则拼接相对路径前缀
return super.formatFileUrl(config.getRelativePathPrefix(), path);
}
return super.formatFileUrl(config.getDomain(), path);
}

View File

@ -21,11 +21,17 @@ public class SftpFileClientConfig implements FileClientConfig {
@NotEmpty(message = "基础路径不能为空")
private String basePath;
@NotNull(message = "是否使用相对路径不能为空")
private Boolean useRelativePath = false;
private String relativePathPrefix = "/file";
/**
* 自定义域名
*/
@NotEmpty(message = "domain 不能为空")
@URL(message = "domain 必须是 URL 格式")
// TODO 王祁 20250515 这里看如何做校验当useRelativePath为true时只校验relativePath否则只校验domain还是说在前端做
// @NotEmpty(message = "domain 不能为空")
// @URL(message = "domain 必须是 URL 格式")
private String domain;
/**