调整文件服务
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.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.db.DBFileClientConfig;
|
||||
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.s3.S3FileClientConfig;
|
||||
@@ -86,8 +85,6 @@ public class FileConfigDO extends BaseDO {
|
||||
String className = JsonUtils.parseObject(json, "@class", String.class);
|
||||
className = StrUtil.subAfter(className, ".", true);
|
||||
switch (className) {
|
||||
case "DBFileClientConfig":
|
||||
return JsonUtils.parseObject2(json, DBFileClientConfig.class);
|
||||
case "FtpFileClientConfig":
|
||||
return JsonUtils.parseObject2(json, FtpFileClientConfig.class);
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public abstract class AbstractFileClient<Config extends FileClientConfig> implem
|
||||
* @return URL 访问地址
|
||||
*/
|
||||
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);
|
||||
FileUtil.writeBytes(content, filePath);
|
||||
// 拼接返回路径
|
||||
return super.formatFileUrl("", path);
|
||||
return super.formatFileUrl(config.getDomain(), path);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,8 +43,11 @@ public class LocalFileClient extends AbstractFileClient<LocalFileClientConfig> {
|
||||
public byte[] getContent(String path) {
|
||||
String filePath = getFilePath(path);
|
||||
return FileUtil.readBytes(filePath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String getFilePath(String 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 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.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.FtpFileClientConfig;
|
||||
import com.tashow.cloud.file.framework.file.core.client.local.LocalFileClient;
|
||||
@@ -25,8 +23,6 @@ import lombok.Getter;
|
||||
@Getter
|
||||
public enum FileStorageEnum {
|
||||
|
||||
DB(1, DBFileClientConfig.class, DBFileClient.class),
|
||||
|
||||
LOCAL(10, LocalFileClientConfig.class, LocalFileClient.class),
|
||||
FTP(11, FtpFileClientConfig.class, FtpFileClient.class),
|
||||
SFTP(12, SftpFileClientConfig.class, SftpFileClient.class),
|
||||
|
||||
@@ -31,6 +31,8 @@ public class SecurityConfiguration {
|
||||
registry.requestMatchers("/druid/**").permitAll();
|
||||
// RPC 服务的安全配置
|
||||
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.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.util.json.JsonUtils;
|
||||
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 jakarta.annotation.Resource;
|
||||
import jakarta.validation.Validator;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
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_NOT_EXISTS;
|
||||
|
||||
@@ -42,21 +48,21 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||
/**
|
||||
* {@link FileClient} 缓存,通过它异步刷新 fileClientFactory
|
||||
*/
|
||||
// @Getter
|
||||
// private final LoadingCache<Long, FileClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
|
||||
// new CacheLoader<Long, FileClient>() {
|
||||
//
|
||||
// @Override
|
||||
// public FileClient load(Long id) {
|
||||
// FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ?
|
||||
// fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id);
|
||||
// if (config != null) {
|
||||
// fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
|
||||
// }
|
||||
// return fileClientFactory.getFileClient(null == config ? id : config.getId());
|
||||
// }
|
||||
//
|
||||
// });
|
||||
@Getter
|
||||
private final LoadingCache<Long, FileClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
|
||||
new CacheLoader<Long, FileClient>() {
|
||||
|
||||
@Override
|
||||
public FileClient load(Long id) {
|
||||
FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ?
|
||||
fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id);
|
||||
if (config != null) {
|
||||
fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
|
||||
}
|
||||
return fileClientFactory.getFileClient(null == config ? id : config.getId());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@Resource
|
||||
private FileClientFactory fileClientFactory;
|
||||
@@ -131,7 +137,7 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||
/**
|
||||
* 清空指定文件配置
|
||||
*
|
||||
* @param id 配置编号
|
||||
* @param id 配置编号
|
||||
* @param master 是否主配置
|
||||
*/
|
||||
private void clearCache(Long id, Boolean master) {
|
||||
@@ -172,12 +178,12 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||
|
||||
@Override
|
||||
public FileClient getFileClient(Long id) {
|
||||
return null;// clientCache.getUnchecked(id);
|
||||
return clientCache.getUnchecked(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileClient getMasterFileClient() {
|
||||
return null;// clientCache.getUnchecked(CACHE_MASTER_ID);
|
||||
return clientCache.getUnchecked(CACHE_MASTER_ID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user