调整文件服务

This commit is contained in:
2025-11-19 09:26:55 +08:00
parent b4f485db09
commit 793a810d65
11 changed files with 87 additions and 178 deletions

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.tashow.cloud.common.util.json.databind;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 文件序列化
*/
public class FileJsonSerializer extends JsonSerializer<String> {
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (StrUtil.isBlank(value)) {
gen.writeString(StrUtil.EMPTY);
return;
}
String[] imgs = value.split(StrUtil.COMMA);
StringBuilder sb = new StringBuilder();
String resourceUrl = "";
String rule="^((http[s]{0,1})://)";
Pattern pattern= Pattern.compile(rule);
// if (Objects.equals(imgUploadUtil.getUploadType(), 2)) {
// resourceUrl = qiniu.getResourcesUrl();
// } else if (Objects.equals(imgUploadUtil.getUploadType(), 1)) {
// resourceUrl = imgUploadUtil.getResourceUrl();
// }
for (String img : imgs) {
Matcher matcher = pattern.matcher(img);
//若图片以http或https开头直接返回
if (matcher.find()){
sb.append(img).append(StrUtil.COMMA);
}else {
sb.append(resourceUrl).append(img).append(StrUtil.COMMA);
}
}
sb.deleteCharAt(sb.length()-1);
gen.writeString(sb.toString());
}
}

View File

@@ -8,7 +8,6 @@ import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.tashow.cloud.common.util.json.JsonUtils; import com.tashow.cloud.common.util.json.JsonUtils;
import com.tashow.cloud.file.framework.file.core.client.FileClientConfig; import com.tashow.cloud.file.framework.file.core.client.FileClientConfig;
import com.tashow.cloud.file.framework.file.core.client.db.DBFileClientConfig;
import com.tashow.cloud.file.framework.file.core.client.ftp.FtpFileClientConfig; import com.tashow.cloud.file.framework.file.core.client.ftp.FtpFileClientConfig;
import com.tashow.cloud.file.framework.file.core.client.local.LocalFileClientConfig; import com.tashow.cloud.file.framework.file.core.client.local.LocalFileClientConfig;
import com.tashow.cloud.file.framework.file.core.client.s3.S3FileClientConfig; import com.tashow.cloud.file.framework.file.core.client.s3.S3FileClientConfig;
@@ -86,8 +85,6 @@ public class FileConfigDO extends BaseDO {
String className = JsonUtils.parseObject(json, "@class", String.class); String className = JsonUtils.parseObject(json, "@class", String.class);
className = StrUtil.subAfter(className, ".", true); className = StrUtil.subAfter(className, ".", true);
switch (className) { switch (className) {
case "DBFileClientConfig":
return JsonUtils.parseObject2(json, DBFileClientConfig.class);
case "FtpFileClientConfig": case "FtpFileClientConfig":
return JsonUtils.parseObject2(json, FtpFileClientConfig.class); return JsonUtils.parseObject2(json, FtpFileClientConfig.class);
case "LocalFileClientConfig": case "LocalFileClientConfig":

View File

@@ -1,47 +0,0 @@
package com.tashow.cloud.file.dal.dataobject.file;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tashow.cloud.file.framework.file.core.client.db.DBFileClient;
import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
import lombok.*;
/**
* 文件内容表
*
* 专门用于存储 {@link DBFileClient} 的文件内容
*
* @author 芋道源码
*/
@TableName("infra_file_content")
@KeySequence("infra_file_content_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FileContentDO extends BaseDO {
/**
* 编号,数据库自增
*/
@TableId
private Long id;
/**
* 配置编号
*
* 关联 {@link FileConfigDO#getId()}
*/
private Long configId;
/**
* 路径,即文件名
*/
private String path;
/**
* 文件内容
*/
private byte[] content;
}

View File

@@ -1,25 +0,0 @@
package com.tashow.cloud.file.dal.mysql.file;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tashow.cloud.file.dal.dataobject.file.FileContentDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface FileContentMapper extends BaseMapper<FileContentDO> {
default void deleteByConfigIdAndPath(Long configId, String path) {
this.delete(new LambdaQueryWrapper<FileContentDO>()
.eq(FileContentDO::getConfigId, configId)
.eq(FileContentDO::getPath, path));
}
default List<FileContentDO> selectListByConfigIdAndPath(Long configId, String path) {
return selectList(new LambdaQueryWrapper<FileContentDO>()
.eq(FileContentDO::getConfigId, configId)
.eq(FileContentDO::getPath, path));
}
}

View File

@@ -58,12 +58,12 @@ public abstract class AbstractFileClient<Config extends FileClientConfig> implem
* 格式化文件的 URL 访问地址 * 格式化文件的 URL 访问地址
* 使用场景local、ftp、db通过 FileController 的 getFile 来获取文件内容 * 使用场景local、ftp、db通过 FileController 的 getFile 来获取文件内容
* *
* @param domain 自定义域名 * @param domain 自定义域名
* @param path 文件路径 * @param path 文件路径
* @return URL 访问地址 * @return URL 访问地址
*/ */
protected String formatFileUrl(String domain, String path) { protected String formatFileUrl(String domain, String path) {
return StrUtil.format("{}/admin-api/infra/file/{}/get/{}", domain, getId(), path); return StrUtil.format("{}/admin-api/file/{}/get/{}", domain, getId(), path);
} }
} }

View File

@@ -1,55 +0,0 @@
package com.tashow.cloud.file.framework.file.core.client.db;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.tashow.cloud.file.dal.dataobject.file.FileContentDO;
import com.tashow.cloud.file.dal.mysql.file.FileContentMapper;
import com.tashow.cloud.file.framework.file.core.client.AbstractFileClient;
import java.util.Comparator;
import java.util.List;
/**
* 基于 DB 存储的文件客户端的配置类
*
* @author 芋道源码
*/
public class DBFileClient extends AbstractFileClient<DBFileClientConfig> {
private FileContentMapper fileContentMapper;
public DBFileClient(Long id, DBFileClientConfig config) {
super(id, config);
}
@Override
protected void doInit() {
fileContentMapper = SpringUtil.getBean(FileContentMapper.class);
}
@Override
public String upload(byte[] content, String path, String type) {
FileContentDO contentDO = new FileContentDO().setConfigId(getId())
.setPath(path).setContent(content);
fileContentMapper.insert(contentDO);
// 拼接返回路径
return super.formatFileUrl(config.getDomain(), path);
}
@Override
public void delete(String path) {
fileContentMapper.deleteByConfigIdAndPath(getId(), path);
}
@Override
public byte[] getContent(String path) {
List<FileContentDO> list = fileContentMapper.selectListByConfigIdAndPath(getId(), path);
if (CollUtil.isEmpty(list)) {
return null;
}
// 排序后,拿 id 最大的,即最后上传的
list.sort(Comparator.comparing(FileContentDO::getId));
return CollUtil.getLast(list).getContent();
}
}

View File

@@ -1,23 +0,0 @@
package com.tashow.cloud.file.framework.file.core.client.db;
import com.tashow.cloud.file.framework.file.core.client.FileClientConfig;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
/**
* 基于 DB 存储的文件客户端的配置类
*
* @author 芋道源码
*/
@Data
public class DBFileClientConfig implements FileClientConfig {
/**
* 自定义域名
*/
@NotEmpty(message = "domain 不能为空")
@URL(message = "domain 必须是 URL 格式")
private String domain;
}

View File

@@ -30,7 +30,7 @@ public class LocalFileClient extends AbstractFileClient<LocalFileClientConfig> {
String filePath = getFilePath(path); String filePath = getFilePath(path);
FileUtil.writeBytes(content, filePath); FileUtil.writeBytes(content, filePath);
// 拼接返回路径 // 拼接返回路径
return super.formatFileUrl("", path); return super.formatFileUrl(config.getDomain(), path);
} }
@Override @Override
@@ -43,8 +43,11 @@ public class LocalFileClient extends AbstractFileClient<LocalFileClientConfig> {
public byte[] getContent(String path) { public byte[] getContent(String path) {
String filePath = getFilePath(path); String filePath = getFilePath(path);
return FileUtil.readBytes(filePath); return FileUtil.readBytes(filePath);
} }
private String getFilePath(String path) { private String getFilePath(String path) {
return config.getBasePath() + path; return config.getBasePath() + path;
} }

View File

@@ -3,8 +3,6 @@ package com.tashow.cloud.file.framework.file.core.enums;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import com.tashow.cloud.file.framework.file.core.client.FileClient; import com.tashow.cloud.file.framework.file.core.client.FileClient;
import com.tashow.cloud.file.framework.file.core.client.FileClientConfig; import com.tashow.cloud.file.framework.file.core.client.FileClientConfig;
import com.tashow.cloud.file.framework.file.core.client.db.DBFileClient;
import com.tashow.cloud.file.framework.file.core.client.db.DBFileClientConfig;
import com.tashow.cloud.file.framework.file.core.client.ftp.FtpFileClient; import com.tashow.cloud.file.framework.file.core.client.ftp.FtpFileClient;
import com.tashow.cloud.file.framework.file.core.client.ftp.FtpFileClientConfig; import com.tashow.cloud.file.framework.file.core.client.ftp.FtpFileClientConfig;
import com.tashow.cloud.file.framework.file.core.client.local.LocalFileClient; import com.tashow.cloud.file.framework.file.core.client.local.LocalFileClient;
@@ -25,8 +23,6 @@ import lombok.Getter;
@Getter @Getter
public enum FileStorageEnum { public enum FileStorageEnum {
DB(1, DBFileClientConfig.class, DBFileClient.class),
LOCAL(10, LocalFileClientConfig.class, LocalFileClient.class), LOCAL(10, LocalFileClientConfig.class, LocalFileClient.class),
FTP(11, FtpFileClientConfig.class, FtpFileClient.class), FTP(11, FtpFileClientConfig.class, FtpFileClient.class),
SFTP(12, SftpFileClientConfig.class, SftpFileClient.class), SFTP(12, SftpFileClientConfig.class, SftpFileClient.class),

View File

@@ -31,6 +31,8 @@ public class SecurityConfiguration {
registry.requestMatchers("/druid/**").permitAll(); registry.requestMatchers("/druid/**").permitAll();
// RPC 服务的安全配置 // RPC 服务的安全配置
registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll(); registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll();
//放行所有接口
registry.requestMatchers( "/**").permitAll();
} }
}; };

View File

@@ -2,6 +2,8 @@ package com.tashow.cloud.file.service.file;
import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.common.util.json.JsonUtils; import com.tashow.cloud.common.util.json.JsonUtils;
import com.tashow.cloud.common.util.validation.ValidationUtils; import com.tashow.cloud.common.util.validation.ValidationUtils;
@@ -16,14 +18,18 @@ import com.tashow.cloud.file.framework.file.core.client.FileClientFactory;
import com.tashow.cloud.file.framework.file.core.enums.FileStorageEnum; import com.tashow.cloud.file.framework.file.core.enums.FileStorageEnum;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Validator; import jakarta.validation.Validator;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.time.Duration;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import static com.tashow.cloud.common.exception.util.ServiceExceptionUtil.exception; import static com.tashow.cloud.common.exception.util.ServiceExceptionUtil.exception;
import static com.tashow.cloud.common.util.cache.CacheUtils.buildAsyncReloadingCache;
import static com.tashow.cloud.fileapi.enums.ErrorCodeConstants.FILE_CONFIG_DELETE_FAIL_MASTER; import static com.tashow.cloud.fileapi.enums.ErrorCodeConstants.FILE_CONFIG_DELETE_FAIL_MASTER;
import static com.tashow.cloud.fileapi.enums.ErrorCodeConstants.FILE_CONFIG_NOT_EXISTS; import static com.tashow.cloud.fileapi.enums.ErrorCodeConstants.FILE_CONFIG_NOT_EXISTS;
@@ -42,21 +48,21 @@ public class FileConfigServiceImpl implements FileConfigService {
/** /**
* {@link FileClient} 缓存,通过它异步刷新 fileClientFactory * {@link FileClient} 缓存,通过它异步刷新 fileClientFactory
*/ */
// @Getter @Getter
// private final LoadingCache<Long, FileClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), private final LoadingCache<Long, FileClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
// new CacheLoader<Long, FileClient>() { new CacheLoader<Long, FileClient>() {
//
// @Override @Override
// public FileClient load(Long id) { public FileClient load(Long id) {
// FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ? FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ?
// fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id); fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id);
// if (config != null) { if (config != null) {
// fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig()); fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
// } }
// return fileClientFactory.getFileClient(null == config ? id : config.getId()); return fileClientFactory.getFileClient(null == config ? id : config.getId());
// } }
//
// }); });
@Resource @Resource
private FileClientFactory fileClientFactory; private FileClientFactory fileClientFactory;
@@ -131,7 +137,7 @@ public class FileConfigServiceImpl implements FileConfigService {
/** /**
* 清空指定文件配置 * 清空指定文件配置
* *
* @param id 配置编号 * @param id 配置编号
* @param master 是否主配置 * @param master 是否主配置
*/ */
private void clearCache(Long id, Boolean master) { private void clearCache(Long id, Boolean master) {
@@ -172,12 +178,12 @@ public class FileConfigServiceImpl implements FileConfigService {
@Override @Override
public FileClient getFileClient(Long id) { public FileClient getFileClient(Long id) {
return null;// clientCache.getUnchecked(id); return clientCache.getUnchecked(id);
} }
@Override @Override
public FileClient getMasterFileClient() { public FileClient getMasterFileClient() {
return null;// clientCache.getUnchecked(CACHE_MASTER_ID); return clientCache.getUnchecked(CACHE_MASTER_ID);
} }
} }