调整文件服务
This commit is contained in:
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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":
|
||||||
|
|||||||
@@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user