reactor:【INFRA】文件上传 api,增加 directory 参数,去除 path 参数,并支持按照日期分目录、文件名不再使用 sha256 而是时间戳

This commit is contained in:
YunaiV
2025-05-02 20:45:53 +08:00
parent 103685269e
commit 8c7331873e
25 changed files with 421 additions and 205 deletions

View File

@@ -8,8 +8,23 @@ import cn.iocoder.yudao.module.infra.framework.file.core.client.ftp.FtpFileClien
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/**
* {@link FtpFileClient} 集成测试
*
* @author 芋道源码
*/
public class FtpFileClientTest {
// docker run -d \
// -p 2121:21 -p 30000-30009:30000-30009 \
// -e FTP_USER=foo \
// -e FTP_PASS=pass \
// -e PASV_ADDRESS=127.0.0.1 \
// -e PASV_MIN_PORT=30000 \
// -e PASV_MAX_PORT=30009 \
// -v $(pwd)/ftp-data:/home/vsftpd \
// fauria/vsftpd
@Test
@Disabled
public void test() {
@@ -17,10 +32,10 @@ public class FtpFileClientTest {
FtpFileClientConfig config = new FtpFileClientConfig();
config.setDomain("http://127.0.0.1:48080");
config.setBasePath("/home/ftp");
config.setHost("kanchai.club");
config.setPort(221);
config.setUsername("");
config.setPassword("");
config.setHost("127.0.0.1");
config.setPort(2121);
config.setUsername("foo");
config.setPassword("pass");
config.setMode(FtpMode.Passive.name());
FtpFileClient client = new FtpFileClient(0L, config);
client.init();

View File

@@ -7,19 +7,29 @@ import cn.iocoder.yudao.module.infra.framework.file.core.client.sftp.SftpFileCli
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/**
* {@link SftpFileClient} 集成测试
*
* @author 芋道源码
*/
public class SftpFileClientTest {
// docker run -p 2222:22 -d \
// -v $(pwd)/sftp-data:/home/foo/upload \
// atmoz/sftp \
// foo:pass:1001
@Test
@Disabled
public void test() {
// 创建客户端
SftpFileClientConfig config = new SftpFileClientConfig();
config.setDomain("http://127.0.0.1:48080");
config.setBasePath("/home/ftp");
config.setHost("kanchai.club");
config.setPort(222);
config.setUsername("");
config.setPassword("");
config.setBasePath("/upload"); // 注意,这个是相对路径,不是实际 linux 上的路径!!!
config.setHost("127.0.0.1");
config.setPort(2222);
config.setUsername("foo");
config.setPassword("pass");
SftpFileClient client = new SftpFileClient(0L, config);
client.init();
// 上传文件

View File

@@ -9,13 +9,14 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper;
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicReference;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
@@ -29,7 +30,7 @@ import static org.mockito.Mockito.*;
public class FileServiceImplTest extends BaseDbUnitTest {
@Resource
private FileService fileService;
private FileServiceImpl fileService;
@Resource
private FileMapper fileMapper;
@@ -37,6 +38,12 @@ public class FileServiceImplTest extends BaseDbUnitTest {
@MockBean
private FileConfigService fileConfigService;
@BeforeEach
public void setUp() {
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true;
FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true;
}
@Test
public void testGetFilePage() {
// mock 数据
@@ -70,28 +77,69 @@ public class FileServiceImplTest extends BaseDbUnitTest {
AssertUtils.assertPojoEquals(dbFile, pageResult.getList().get(0));
}
/**
* content、name、directory、type 都非空
*/
@Test
public void testCreateFile_success() throws Exception {
public void testCreateFile_success_01() throws Exception {
// 准备参数
String path = randomString();
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
String name = "单测文件名";
String directory = randomString();
String type = "image/jpeg";
// mock Master 文件客户端
FileClient client = mock(FileClient.class);
when(fileConfigService.getMasterFileClient()).thenReturn(client);
String url = randomString();
when(client.upload(same(content), same(path), eq("image/jpeg"))).thenReturn(url);
AtomicReference<String> pathRef = new AtomicReference<>();
when(client.upload(same(content), argThat(path -> {
assertTrue(path.matches(directory + "/\\d{8}/" + name + "_\\d+.jpg"));
pathRef.set(path);
return true;
}), eq(type))).thenReturn(url);
when(client.getId()).thenReturn(10L);
String name = "单测文件名";
// 调用
String result = fileService.createFile(name, path, content);
String result = fileService.createFile(content, name, directory, type);
// 断言
assertEquals(result, url);
// 校验数据
FileDO file = fileMapper.selectOne(FileDO::getPath, path);
FileDO file = fileMapper.selectOne(FileDO::getUrl, url);
assertEquals(10L, file.getConfigId());
assertEquals(path, file.getPath());
assertEquals(pathRef.get(), file.getPath());
assertEquals(url, file.getUrl());
assertEquals("image/jpeg", file.getType());
assertEquals(type, file.getType());
assertEquals(content.length, file.getSize());
}
/**
* content 非空,其它都空
*/
@Test
public void testCreateFile_success_02() throws Exception {
// 准备参数
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
// mock Master 文件客户端
String type = "image/jpeg";
FileClient client = mock(FileClient.class);
when(fileConfigService.getMasterFileClient()).thenReturn(client);
String url = randomString();
AtomicReference<String> pathRef = new AtomicReference<>();
when(client.upload(same(content), argThat(path -> {
assertTrue(path.matches("\\d{8}/6318848e882d8a7e7e82789d87608f684ee52d41966bfc8cad3ce15aad2b970e_\\d+\\.jpg"));
pathRef.set(path);
return true;
}), eq(type))).thenReturn(url);
when(client.getId()).thenReturn(10L);
// 调用
String result = fileService.createFile(content, null, null, null);
// 断言
assertEquals(result, url);
// 校验数据
FileDO file = fileMapper.selectOne(FileDO::getUrl, url);
assertEquals(10L, file.getConfigId());
assertEquals(pathRef.get(), file.getPath());
assertEquals(url, file.getUrl());
assertEquals(type, file.getType());
assertEquals(content.length, file.getSize());
}
@@ -140,4 +188,122 @@ public class FileServiceImplTest extends BaseDbUnitTest {
assertSame(result, content);
}
@Test
public void testGenerateUploadPath_AllEnabled() {
// 准备参数
String name = "test.jpg";
String directory = "avatar";
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true;
FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true;
// 调用
String path = fileService.generateUploadPath(name, directory);
// 断言
// 格式为avatar/yyyyMMdd/test_timestamp.jpg
assertTrue(path.startsWith(directory + "/"));
// 包含日期格式8 位数字,如 20240517
assertTrue(path.matches(directory + "/\\d{8}/test_\\d+\\.jpg"));
}
@Test
public void testGenerateUploadPath_PrefixEnabled_SuffixDisabled() {
// 准备参数
String name = "test.jpg";
String directory = "avatar";
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true;
FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = false;
// 调用
String path = fileService.generateUploadPath(name, directory);
// 断言
// 格式为avatar/yyyyMMdd/test.jpg
assertTrue(path.startsWith(directory + "/"));
// 包含日期格式8 位数字,如 20240517
assertTrue(path.matches(directory + "/\\d{8}/test\\.jpg"));
}
@Test
public void testGenerateUploadPath_PrefixDisabled_SuffixEnabled() {
// 准备参数
String name = "test.jpg";
String directory = "avatar";
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = false;
FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true;
// 调用
String path = fileService.generateUploadPath(name, directory);
// 断言
// 格式为avatar/test_timestamp.jpg
assertTrue(path.startsWith(directory + "/"));
assertTrue(path.matches(directory + "/test_\\d+\\.jpg"));
}
@Test
public void testGenerateUploadPath_AllDisabled() {
// 准备参数
String name = "test.jpg";
String directory = "avatar";
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = false;
FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = false;
// 调用
String path = fileService.generateUploadPath(name, directory);
// 断言
// 格式为avatar/test.jpg
assertEquals(directory + "/" + name, path);
}
@Test
public void testGenerateUploadPath_NoExtension() {
// 准备参数
String name = "test";
String directory = "avatar";
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true;
FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true;
// 调用
String path = fileService.generateUploadPath(name, directory);
// 断言
// 格式为avatar/yyyyMMdd/test_timestamp
assertTrue(path.startsWith(directory + "/"));
assertTrue(path.matches(directory + "/\\d{8}/test_\\d+"));
}
@Test
public void testGenerateUploadPath_DirectoryNull() {
// 准备参数
String name = "test.jpg";
String directory = null;
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true;
FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true;
// 调用
String path = fileService.generateUploadPath(name, directory);
// 断言
// 格式为yyyyMMdd/test_timestamp.jpg
assertTrue(path.matches("\\d{8}/test_\\d+\\.jpg"));
}
@Test
public void testGenerateUploadPath_DirectoryEmpty() {
// 准备参数
String name = "test.jpg";
String directory = "";
FileServiceImpl.PATH_PREFIX_DATE_ENABLE = true;
FileServiceImpl.PATH_SUFFIX_TIMESTAMP_ENABLE = true;
// 调用
String path = fileService.generateUploadPath(name, directory);
// 断言
// 格式为yyyyMMdd/test_timestamp.jpg
assertTrue(path.matches("\\d{8}/test_\\d+\\.jpg"));
}
}