refactor: 优化文件存储路径代码

This commit is contained in:
AgAngle 2023-11-17 17:10:09 +08:00 committed by jianxing
parent ddc78c44f8
commit 733b063bb8
14 changed files with 223 additions and 97 deletions

View File

@ -0,0 +1,67 @@
package io.metersphere.sdk.constants;
/**
* @Author: jianxing
* @CreateTime: 2023-11-17 14:04
*/
public class DefaultRepositoryDir {
/**
* 系统级别资源的根目录
*/
private static final String SYSTEM_ROOT_DIR = "system";
/**
* 组织级别资源的项目目录
* organization/{organizationId}
*/
private static final String ORGANIZATION_DIR = "organization/%s";
/**
* 项目级别资源的项目目录
* project/{projectId}
*/
private static final String PROJECT_DIR = "project/%s";
/*------ start: 系统下资源目录 ------*/
/**
* 插件存储目录
*/
private static final String SYSTEM_PLUGIN_DIR = SYSTEM_ROOT_DIR + "/plugin";
/*------ end: 系统下资源目录 --------*/
/*------ start: 项目下资源目录 --------*/
/**
* 接口用例相关文件的存储目录
* project/{projectId}/apiCase/{apiCaseId}
*/
private static final String PROJECT_API_CASE_DIR = PROJECT_DIR + "/apiCase/%s";
private static final String PROJECT_FUNCTIONAL_CASE_DIR = PROJECT_DIR + "/functionalCase/%s";
private static final String PROJECT_FILE_MANAGEMENT_DIR = PROJECT_DIR + "/fileManagement";
private static final String PROJECT_BUG_DIR = PROJECT_DIR + "/bug/%s";
/*------ end: 项目下资源目录 --------*/
public static String getApiCaseDir(String projectId, String apiCaseId) {
return String.format(PROJECT_API_CASE_DIR, projectId, apiCaseId);
}
public static String getPluginDir() {
return SYSTEM_PLUGIN_DIR;
}
public static String getFunctionalCaseDir(String projectId, String functionalCaseId) {
return String.format(PROJECT_FUNCTIONAL_CASE_DIR, projectId, functionalCaseId);
}
public static String getFileManagementDir(String projectId) {
return String.format(PROJECT_FILE_MANAGEMENT_DIR, projectId);
}
public static String getBugDir(String projectId, String bugId) {
return String.format(PROJECT_BUG_DIR, projectId, bugId);
}
}

View File

@ -0,0 +1,42 @@
package io.metersphere.sdk.constants;
/**
* @Author: jianxing
* @CreateTime: 2023-11-17 13:54
*/
public class LocalRepositoryDir {
/**
* 本地存储文件的根目录
*/
private static final String ROOT_DIR = "/opt/metersphere/data/app";
/**
* 系统级别资源的根目录
*/
private static final String SYSTEM_ROOT_DIR = ROOT_DIR + "/" + "system";
/**
* 组织级别资源的项目目录
* organization/{organizationId}
*/
private static final String ORGANIZATION_DIR = ROOT_DIR + "/organization/%s";
/**
* 项目级别资源的项目目录
* project/{projectId}
*/
private static final String PROJECT_DIR = ROOT_DIR + "/project/%s";
/*------ start: 系统下资源目录 ------*/
/**
* 插件存储目录
*/
private static final String SYSTEM_PLUGIN_DIR = SYSTEM_ROOT_DIR + "/plugin";
private static final String SYSTEM_BODY_ENVIRONMENT_TEM_DIR = SYSTEM_ROOT_DIR + "/body/environment/tmp";
/*------ end: 系统下资源目录 --------*/
public static String getPluginDir() {
return SYSTEM_PLUGIN_DIR;
}
public static String getBodyEnvironmentTmpDir() {
return SYSTEM_BODY_ENVIRONMENT_TEM_DIR;
}
}

View File

@ -6,13 +6,6 @@ import org.apache.commons.lang3.StringUtils;
import java.io.File; import java.io.File;
public class MsFileUtils { public class MsFileUtils {
public static final String DATA_ROOT_DIR = "/opt/metersphere/data/app";
public static final String PLUGIN_DIR_NAME = "plugins";
public static final String PLUGIN_DIR = DATA_ROOT_DIR + "/" + PLUGIN_DIR_NAME;
public static final String FUNCTIONAL_CASE_DIR_NAME = "functionalCase";
public static final String BUG_MANAGEMENT_DIR = "bug";
public static void validateFileName(String... fileNames) { public static void validateFileName(String... fileNames) {
if (fileNames != null) { if (fileNames != null) {
for (String fileName : fileNames) { for (String fileName : fileNames) {

View File

@ -11,6 +11,7 @@ import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.DefaultRepositoryDir;
import io.metersphere.sdk.constants.StorageType; import io.metersphere.sdk.constants.StorageType;
import io.metersphere.sdk.domain.Environment; import io.metersphere.sdk.domain.Environment;
import io.metersphere.sdk.domain.EnvironmentExample; import io.metersphere.sdk.domain.EnvironmentExample;
@ -42,9 +43,6 @@ public class ApiTestCaseService {
public static final Long ORDER_STEP = 5000L; public static final Long ORDER_STEP = 5000L;
private static final String MAIN_FOLDER_PROJECT = "project";
private static final String APP_NAME_API_CASE = "apiCase";
@Resource @Resource
private ApiTestCaseMapper apiTestCaseMapper; private ApiTestCaseMapper apiTestCaseMapper;
@Resource @Resource
@ -135,8 +133,7 @@ public class ApiTestCaseService {
files.forEach(file -> { files.forEach(file -> {
FileRequest fileRequest = new FileRequest(); FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(file.getName()); fileRequest.setFileName(file.getName());
fileRequest.setFolder(minioPath(projectId)); fileRequest.setFolder(DefaultRepositoryDir.getApiCaseDir(projectId, caseId));
fileRequest.setResourceId(caseId);
fileRequest.setStorage(StorageType.MINIO.name()); fileRequest.setStorage(StorageType.MINIO.name());
try { try {
minioRepository.saveFile(file, fileRequest); minioRepository.saveFile(file, fileRequest);
@ -226,8 +223,7 @@ public class ApiTestCaseService {
apiTestCaseFollowerMapper.deleteByExample(example); apiTestCaseFollowerMapper.deleteByExample(example);
try { try {
FileRequest request = new FileRequest(); FileRequest request = new FileRequest();
request.setFolder(minioPath(apiCase.getProjectId())); request.setFolder(DefaultRepositoryDir.getApiCaseDir(apiCase.getProjectId(), id));
request.setResourceId(id);
minioRepository.deleteFolder(request); minioRepository.deleteFolder(request);
} catch (Exception e) { } catch (Exception e) {
LogUtils.info("删除body文件失败: 文件名称:" + id, e); LogUtils.info("删除body文件失败: 文件名称:" + id, e);
@ -294,8 +290,4 @@ public class ApiTestCaseService {
}); });
} }
} }
private String minioPath(String projectId) {
return StringUtils.join(MAIN_FOLDER_PROJECT, "/", projectId, "/", APP_NAME_API_CASE);
}
} }

View File

@ -16,10 +16,7 @@ import io.metersphere.project.dto.filemanagement.FileLogRecord;
import io.metersphere.project.service.FileAssociationService; import io.metersphere.project.service.FileAssociationService;
import io.metersphere.project.service.FileService; import io.metersphere.project.service.FileService;
import io.metersphere.project.service.ProjectTemplateService; import io.metersphere.project.service.ProjectTemplateService;
import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.StorageType;
import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.FileAssociationSourceUtil; import io.metersphere.sdk.util.FileAssociationSourceUtil;
@ -93,8 +90,6 @@ public class BugService {
public static final String ADD_BUG_FILE_LOG_URL = "/bug/add"; public static final String ADD_BUG_FILE_LOG_URL = "/bug/add";
public static final String UPDATE_BUG_FILE_LOG_URL = "/bug/update"; public static final String UPDATE_BUG_FILE_LOG_URL = "/bug/update";
public static final String UPLOAD_SOURCE_DIR = "/project";
public static final String UPLOAD_APP_DIR = "/bug";
/** /**
* 缺陷列表查询 * 缺陷列表查询
@ -644,9 +639,7 @@ public class BugService {
private FileRequest buildBugFileRequest(String projectId, String resourceId, String fileName) { private FileRequest buildBugFileRequest(String projectId, String resourceId, String fileName) {
FileRequest fileRequest = new FileRequest(); FileRequest fileRequest = new FileRequest();
fileRequest.setFolder(UPLOAD_SOURCE_DIR + "/" + projectId + UPLOAD_APP_DIR + "/" + resourceId); fileRequest.setFolder(DefaultRepositoryDir.getBugDir(projectId, resourceId));
fileRequest.setProjectId(projectId);
fileRequest.setResourceId(resourceId);
fileRequest.setFileName(StringUtils.isEmpty(fileName) ? null : fileName); fileRequest.setFileName(StringUtils.isEmpty(fileName) ? null : fileName);
fileRequest.setStorage(StorageType.MINIO.name()); fileRequest.setStorage(StorageType.MINIO.name());
return fileRequest; return fileRequest;

View File

@ -18,8 +18,6 @@ public class DeleteFunctionalCaseService {
@Resource @Resource
private FunctionalCaseTestMapper functionalCaseTestMapper; private FunctionalCaseTestMapper functionalCaseTestMapper;
@Resource @Resource
private FunctionalCaseAttachmentService functionalCaseAttachmentService;
@Resource
private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper; private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper;
@Resource @Resource
private FunctionalCaseBlobMapper functionalCaseBlobMapper; private FunctionalCaseBlobMapper functionalCaseBlobMapper;
@ -39,8 +37,7 @@ public class DeleteFunctionalCaseService {
FunctionalCaseCommentExample functionalCaseCommentExample = new FunctionalCaseCommentExample(); FunctionalCaseCommentExample functionalCaseCommentExample = new FunctionalCaseCommentExample();
functionalCaseCommentExample.createCriteria().andCaseIdIn(ids); functionalCaseCommentExample.createCriteria().andCaseIdIn(ids);
functionalCaseCommentMapper.deleteByExample(functionalCaseCommentExample); functionalCaseCommentMapper.deleteByExample(functionalCaseCommentExample);
//9.附件 //9.附件 todo 删除关联关系
functionalCaseAttachmentService.deleteAttachmentResource(ids, projectId);
//10.自定义字段 //10.自定义字段
FunctionalCaseCustomFieldExample fieldExample = new FunctionalCaseCustomFieldExample(); FunctionalCaseCustomFieldExample fieldExample = new FunctionalCaseCustomFieldExample();
fieldExample.createCriteria().andCaseIdIn(ids); fieldExample.createCriteria().andCaseIdIn(ids);

View File

@ -10,10 +10,10 @@ import io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper;
import io.metersphere.functional.request.FunctionalCaseAddRequest; import io.metersphere.functional.request.FunctionalCaseAddRequest;
import io.metersphere.project.domain.FileMetadata; import io.metersphere.project.domain.FileMetadata;
import io.metersphere.project.mapper.FileMetadataMapper; import io.metersphere.project.mapper.FileMetadataMapper;
import io.metersphere.sdk.constants.DefaultRepositoryDir;
import io.metersphere.sdk.constants.StorageType; import io.metersphere.sdk.constants.StorageType;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.MsFileUtils;
import io.metersphere.system.file.FileRequest; import io.metersphere.system.file.FileRequest;
import io.metersphere.system.file.MinioRepository; import io.metersphere.system.file.MinioRepository;
import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.IDGenerator;
@ -52,8 +52,6 @@ public class FunctionalCaseAttachmentService {
@Resource @Resource
private MinioRepository minioRepository; private MinioRepository minioRepository;
public static final String UPLOAD_SOURCE_DIR = "/project";
/** /**
* 保存本地上传文件和用例关联关系 * 保存本地上传文件和用例关联关系
* *
@ -81,7 +79,7 @@ public class FunctionalCaseAttachmentService {
String fileId = IDGenerator.nextStr(); String fileId = IDGenerator.nextStr();
FileRequest fileRequest = new FileRequest(); FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(file.getName()); fileRequest.setFileName(file.getName());
fileRequest.setResourceId(UPLOAD_SOURCE_DIR + "/" + request.getProjectId() + "/" + MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + fileId); fileRequest.setFolder(DefaultRepositoryDir.getFunctionalCaseDir(request.getProjectId(), caseId) + "/" + fileId);
fileRequest.setStorage(StorageType.MINIO.name()); fileRequest.setStorage(StorageType.MINIO.name());
try { try {
minioRepository.saveFile(file, fileRequest); minioRepository.saveFile(file, fileRequest);
@ -167,16 +165,16 @@ public class FunctionalCaseAttachmentService {
example.clear(); example.clear();
example.createCriteria().andFileIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId); example.createCriteria().andFileIdIn(deleteFileMetaIds).andCaseIdEqualTo(caseId);
functionalCaseAttachmentMapper.deleteByExample(example); functionalCaseAttachmentMapper.deleteByExample(example);
this.deleteMinioFile(delAttachment, projectId); this.deleteMinioFile(delAttachment, projectId, caseId);
} }
private void deleteMinioFile(List<FunctionalCaseAttachment> files, String projectId) { private void deleteMinioFile(List<FunctionalCaseAttachment> files, String caseId, String projectId) {
if (CollectionUtils.isNotEmpty(files)) { if (CollectionUtils.isNotEmpty(files)) {
files.forEach(file -> { files.forEach(file -> {
FileRequest fileRequest = new FileRequest(); FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(file.getFileName()); fileRequest.setFileName(file.getFileName());
fileRequest.setResourceId(UPLOAD_SOURCE_DIR + "/" + projectId + "/" + MsFileUtils.FUNCTIONAL_CASE_DIR_NAME + "/" + file.getFileId()); fileRequest.setFolder(DefaultRepositoryDir.getFunctionalCaseDir(projectId, caseId) + "/" + file.getFileId());
fileRequest.setStorage(StorageType.MINIO.name()); fileRequest.setStorage(StorageType.MINIO.name());
try { try {
minioRepository.delete(fileRequest); minioRepository.delete(fileRequest);
@ -187,23 +185,6 @@ public class FunctionalCaseAttachmentService {
} }
} }
/**
* 清理附件资源
*
* @param ids
*/
public void deleteAttachmentResource(List<String> ids, String projectId) {
FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample();
example.createCriteria().andCaseIdIn(ids).andLocalEqualTo(true);
List<FunctionalCaseAttachment> localAttachment = functionalCaseAttachmentMapper.selectByExample(example);
example.clear();
example.createCriteria().andCaseIdIn(ids);
functionalCaseAttachmentMapper.deleteByExample(example);
deleteMinioFile(localAttachment, projectId);
}
/** /**
* 通过caseId获取附件信息 * 通过caseId获取附件信息
* *

View File

@ -2,6 +2,7 @@ package io.metersphere.project.service;
import io.metersphere.project.dto.environment.ssl.KeyStoreEntry; import io.metersphere.project.dto.environment.ssl.KeyStoreEntry;
import io.metersphere.sdk.constants.LocalRepositoryDir;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
@ -24,7 +25,7 @@ public class CommandService {
public static String createFile(MultipartFile bodyFile) { public static String createFile(MultipartFile bodyFile) {
MsFileUtils.validateFileName(bodyFile.getOriginalFilename()); MsFileUtils.validateFileName(bodyFile.getOriginalFilename());
String dir = MsFileUtils.DATA_ROOT_DIR + "/body/environment/tmp"; String dir = LocalRepositoryDir.getBodyEnvironmentTmpDir();
File fileDir = new File(dir); File fileDir = new File(dir);
if (!fileDir.exists()) { if (!fileDir.exists()) {
fileDir.mkdirs(); fileDir.mkdirs();

View File

@ -13,6 +13,7 @@ import io.metersphere.project.mapper.FileMetadataMapper;
import io.metersphere.project.mapper.FileMetadataRepositoryMapper; import io.metersphere.project.mapper.FileMetadataRepositoryMapper;
import io.metersphere.project.mapper.FileModuleRepositoryMapper; import io.metersphere.project.mapper.FileModuleRepositoryMapper;
import io.metersphere.project.utils.FileDownloadUtils; import io.metersphere.project.utils.FileDownloadUtils;
import io.metersphere.sdk.constants.DefaultRepositoryDir;
import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.StorageType; import io.metersphere.sdk.constants.StorageType;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
@ -674,10 +675,7 @@ public class FileMetadataService {
return fileVersionResponseList; return fileVersionResponseList;
} }
private static final String MAIN_FOLDER_PROJECT = "project";
private static final String APP_NAME_FILE_MANAGEMENT = "fileManagement";
private String generateMinIOFilePath(String projectId) { private String generateMinIOFilePath(String projectId) {
return StringUtils.join(MAIN_FOLDER_PROJECT, "/", projectId, "/", APP_NAME_FILE_MANAGEMENT); return DefaultRepositoryDir.getFileManagementDir(projectId);
} }
} }

View File

@ -10,13 +10,19 @@ public class FileRequest {
private String folder; private String folder;
//项目ID /**
* @Deprecated 月底移除
*/
@Deprecated(since="3.x", forRemoval=true)
private String projectId; private String projectId;
// 存储类型 // 存储类型
private String storage; private String storage;
// 资源id为空时存储在项目目录下 /**
* @Deprecated 月底移除
*/
@Deprecated(since="3.x", forRemoval=true)
private String resourceId; private String resourceId;
// 文件名称 // 文件名称

View File

@ -16,10 +16,10 @@ public class LocalFileRepository implements FileRepository {
@Override @Override
public String saveFile(MultipartFile multipartFile, FileRequest request) throws IOException { public String saveFile(MultipartFile multipartFile, FileRequest request) throws IOException {
if (multipartFile == null || request == null || StringUtils.isEmpty(request.getFileName()) || StringUtils.isEmpty(request.getProjectId())) { if (multipartFile == null || request == null || StringUtils.isEmpty(request.getFileName()) || StringUtils.isEmpty(request.getFolder())) {
return null; return null;
} }
MsFileUtils.validateFileName(request.getProjectId(), request.getFileName()); MsFileUtils.validateFileName(request.getFolder(), request.getFileName());
createFileDir(request); createFileDir(request);
File file = new File(getFilePath(request)); File file = new File(getFilePath(request));
FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file); FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
@ -62,7 +62,7 @@ public class LocalFileRepository implements FileRepository {
@Override @Override
public void deleteFolder(FileRequest request) throws Exception { public void deleteFolder(FileRequest request) throws Exception {
MsFileUtils.validateFileName(request.getProjectId(), request.getFileName()); MsFileUtils.validateFileName(request.getFolder(), request.getFileName());
this.delete(request); this.delete(request);
} }
@ -88,12 +88,12 @@ public class LocalFileRepository implements FileRepository {
} }
private String getFilePath(FileRequest request) { private String getFilePath(FileRequest request) {
MsFileUtils.validateFileName(request.getProjectId(), request.getFileName()); MsFileUtils.validateFileName(request.getFolder(), request.getFileName());
return StringUtils.join(getFileDir(request), "/", request.getFileName()); return StringUtils.join(getFileDir(request), "/", request.getFileName());
} }
private String getFileDir(FileRequest request) { private String getFileDir(FileRequest request) {
MsFileUtils.validateFileName(request.getProjectId(), request.getFileName()); MsFileUtils.validateFileName(request.getFolder(), request.getFileName());
return StringUtils.join(MsFileUtils.DATA_ROOT_DIR, "/", request.getProjectId()); return request.getFolder();
} }
} }

View File

@ -1,6 +1,8 @@
package io.metersphere.system.service; package io.metersphere.system.service;
import io.metersphere.plugin.sdk.spi.MsPlugin; import io.metersphere.plugin.sdk.spi.MsPlugin;
import io.metersphere.sdk.constants.DefaultRepositoryDir;
import io.metersphere.sdk.constants.LocalRepositoryDir;
import io.metersphere.sdk.constants.StorageType; import io.metersphere.sdk.constants.StorageType;
import io.metersphere.system.controller.handler.result.CommonResultCode; import io.metersphere.system.controller.handler.result.CommonResultCode;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
@ -56,7 +58,7 @@ public class PluginLoadService {
*/ */
public String loadPlugin(String fileName) { public String loadPlugin(String fileName) {
MsFileUtils.validateFileName(fileName); MsFileUtils.validateFileName(fileName);
String filePath = MsFileUtils.PLUGIN_DIR + "/" + fileName; String filePath = LocalRepositoryDir.getPluginDir() + "/" + fileName;
File file = new File(filePath); File file = new File(filePath);
if (!file.exists()) { if (!file.exists()) {
// 文件不存在则从对象存储重新下载 // 文件不存在则从对象存储重新下载
@ -74,11 +76,12 @@ public class PluginLoadService {
*/ */
public void loadPluginFromRepository(String fileName) { public void loadPluginFromRepository(String fileName) {
MsFileUtils.validateFileName(fileName); MsFileUtils.validateFileName(fileName);
String filePath = MsFileUtils.PLUGIN_DIR + "/" + fileName; String filePath = LocalRepositoryDir.getPluginDir() + "/" + fileName;
File file = new File(filePath); File file = new File(filePath);
try { try {
if (!file.exists()) { if (!file.exists()) {
InputStream fileAsStream = FileCenter.getDefaultRepository().getFileAsStream(getFileRequest(fileName)); InputStream fileAsStream = FileCenter.getDefaultRepository()
.getFileAsStream(getDefaultRepositoryFileRequest(fileName));
FileUtils.copyInputStreamToFile(fileAsStream, file); FileUtils.copyInputStreamToFile(fileAsStream, file);
} }
msPluginManager.loadPlugin(Paths.get(filePath)); msPluginManager.loadPlugin(Paths.get(filePath));
@ -95,7 +98,8 @@ public class PluginLoadService {
*/ */
public String uploadPlugin2Local(MultipartFile file) { public String uploadPlugin2Local(MultipartFile file) {
try { try {
return FileCenter.getRepository(StorageType.LOCAL).saveFile(file, getFileRequest(file.getOriginalFilename())); return FileCenter.getRepository(StorageType.LOCAL)
.saveFile(file, getLocalRepositoryFileRequest(file.getOriginalFilename()));
} catch (Exception e) { } catch (Exception e) {
LogUtils.error(e); LogUtils.error(e);
throw new MSException("文件上传异常", e); throw new MSException("文件上传异常", e);
@ -109,7 +113,8 @@ public class PluginLoadService {
*/ */
public void uploadPlugin2Repository(MultipartFile file) { public void uploadPlugin2Repository(MultipartFile file) {
try { try {
FileCenter.getDefaultRepository().saveFile(file, getFileRequest(file.getOriginalFilename())); FileCenter.getDefaultRepository()
.saveFile(file, getDefaultRepositoryFileRequest(file.getOriginalFilename()));
} catch (Exception e) { } catch (Exception e) {
LogUtils.error(e); LogUtils.error(e);
throw new MSException("文件上传异常", e); throw new MSException("文件上传异常", e);
@ -123,17 +128,26 @@ public class PluginLoadService {
*/ */
public void downloadPluginFromRepository(String fileName) { public void downloadPluginFromRepository(String fileName) {
try { try {
InputStream inputStream = FileCenter.getDefaultRepository().getFileAsStream(getFileRequest(fileName)); InputStream inputStream = FileCenter.getDefaultRepository()
FileCenter.getRepository(StorageType.LOCAL).saveFile(inputStream, getFileRequest(fileName)); .getFileAsStream(getDefaultRepositoryFileRequest(fileName));
FileCenter.getRepository(StorageType.LOCAL)
.saveFile(inputStream, getLocalRepositoryFileRequest(fileName));
} catch (Exception e) { } catch (Exception e) {
LogUtils.error(e); LogUtils.error(e);
throw new MSException("下载插件异常", e); throw new MSException("下载插件异常", e);
} }
} }
private FileRequest getFileRequest(String name) { private FileRequest getDefaultRepositoryFileRequest(String name) {
FileRequest request = new FileRequest(); FileRequest request = new FileRequest();
request.setProjectId(MsFileUtils.PLUGIN_DIR_NAME); request.setFolder(DefaultRepositoryDir.getPluginDir());
request.setFileName(name);
return request;
}
private FileRequest getLocalRepositoryFileRequest(String name) {
FileRequest request = new FileRequest();
request.setFolder(LocalRepositoryDir.getPluginDir());
request.setFileName(name); request.setFileName(name);
return request; return request;
} }
@ -202,10 +216,10 @@ public class PluginLoadService {
* 删除插件 * 删除插件
*/ */
public void deletePluginFile(String fileName) { public void deletePluginFile(String fileName) {
FileRequest fileRequest = getFileRequest(fileName);
try { try {
FileCenter.getRepository(StorageType.LOCAL).delete(fileRequest); this.deleteLocalPluginFile(fileName);
FileCenter.getDefaultRepository().delete(fileRequest); FileCenter.getDefaultRepository()
.delete(getDefaultRepositoryFileRequest(fileName));
} catch (Exception e) { } catch (Exception e) {
LogUtils.error(e); LogUtils.error(e);
} }
@ -216,9 +230,10 @@ public class PluginLoadService {
* @param fileName * @param fileName
*/ */
public void deleteLocalPluginFile(String fileName) { public void deleteLocalPluginFile(String fileName) {
FileRequest fileRequest = getFileRequest(fileName); FileRequest fileRequest = getLocalRepositoryFileRequest(fileName);
try { try {
FileCenter.getRepository(StorageType.LOCAL).delete(fileRequest); FileCenter.getRepository(StorageType.LOCAL)
.delete(fileRequest);
} catch (Exception e) { } catch (Exception e) {
LogUtils.error(e); LogUtils.error(e);
} }

View File

@ -35,24 +35,25 @@ public class FileCenterTests {
"Hello, World!".getBytes() "Hello, World!".getBytes()
); );
// 创建一个FileRequest对象作为测试用的请求参数 // 创建一个FileRequest对象作为测试用的请求参数
FileRequest request = new FileRequest(); FileRequest request = getFileRequest();
request.setFileName("test.txt");
request.setProjectId("test-project");
request.setResourceId("test-resource-id");
repository.saveFile(mockFile, request); repository.saveFile(mockFile, request);
Assertions.assertTrue(repository.saveFile(mockFile, request) != null); Assertions.assertTrue(repository.saveFile(mockFile, request) != null);
Assertions.assertTrue(repository.saveFile("Hello, World!".getBytes(), request) != null); Assertions.assertTrue(repository.saveFile("Hello, World!".getBytes(), request) != null);
} }
private static FileRequest getFileRequest() {
FileRequest request = new FileRequest();
request.setFileName("test.txt");
request.setFolder("test-project/test-resource-id");
return request;
}
@Test @Test
@Order(3) @Order(3)
public void testGetFile() throws Exception { public void testGetFile() throws Exception {
// 创建一个FileRequest对象作为测试用的请求参数 // 创建一个FileRequest对象作为测试用的请求参数
FileRequest request = new FileRequest(); FileRequest request = getFileRequest();
request.setFileName("test.txt");
request.setProjectId("test-project");
request.setResourceId("test-resource-id");
repository.getFile(request); repository.getFile(request);
Assertions.assertTrue(repository.getFile(request) != null); Assertions.assertTrue(repository.getFile(request) != null);
} }
@ -61,11 +62,7 @@ public class FileCenterTests {
@Order(4) @Order(4)
public void testDelFile() throws Exception { public void testDelFile() throws Exception {
// 创建一个FileRequest对象作为测试用的请求参数 // 创建一个FileRequest对象作为测试用的请求参数
FileRequest request = new FileRequest(); repository.delete(getFileRequest());
request.setFileName("test.txt");
request.setProjectId("test-project");
request.setResourceId("test-resource-id");
repository.delete(request);
} }
@Test @Test
@ -80,7 +77,7 @@ public class FileCenterTests {
// 创建一个FileRequest对象作为测试用的请求参数 // 创建一个FileRequest对象作为测试用的请求参数
FileRequest request = new FileRequest(); FileRequest request = new FileRequest();
request.setFileName("test.txt"); request.setFileName("test.txt");
request.setProjectId("test-project"); request.setFolder("test-project");
repository.saveFile(mockFile, request); repository.saveFile(mockFile, request);
Assertions.assertTrue(repository.saveFile(mockFile, request) != null); Assertions.assertTrue(repository.saveFile(mockFile, request) != null);
Assertions.assertTrue(repository.saveFile("Hello, World!".getBytes(), request) != null); Assertions.assertTrue(repository.saveFile("Hello, World!".getBytes(), request) != null);

View File

@ -1,5 +1,6 @@
package io.metersphere.system.controller; package io.metersphere.system.controller;
import io.metersphere.plugin.platform.spi.Platform;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.PluginScenarioType; import io.metersphere.sdk.constants.PluginScenarioType;
import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.sdk.constants.SessionConstants;
@ -11,6 +12,8 @@ import io.metersphere.system.domain.*;
import io.metersphere.system.dto.OrganizationDTO; import io.metersphere.system.dto.OrganizationDTO;
import io.metersphere.system.dto.PluginDTO; import io.metersphere.system.dto.PluginDTO;
import io.metersphere.system.dto.sdk.OptionDTO; import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.file.FileRequest;
import io.metersphere.system.file.LocalFileRepository;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.mapper.PluginMapper; import io.metersphere.system.mapper.PluginMapper;
import io.metersphere.system.mapper.PluginOrganizationMapper; import io.metersphere.system.mapper.PluginOrganizationMapper;
@ -27,11 +30,13 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -67,11 +72,13 @@ public class PluginControllerTests extends BaseTest {
private JdbcDriverPluginService jdbcDriverPluginService; private JdbcDriverPluginService jdbcDriverPluginService;
@Resource @Resource
private PluginScriptService pluginScriptService; private PluginScriptService pluginScriptService;
@Resource
private LocalFileRepository localFileRepository;
private static Plugin addPlugin; private static Plugin addPlugin;
private static Plugin anotherAddPlugin; private static Plugin anotherAddPlugin;
@Resource @Resource
private PluginService pluginService; private PluginLoadService pluginLoadService;
public static final String PLUGIN_OPTIONS_URL = "/plugin/options"; public static final String PLUGIN_OPTIONS_URL = "/plugin/options";
@Resource @Resource
private MockServerClient mockServerClient; private MockServerClient mockServerClient;
@ -128,6 +135,19 @@ public class PluginControllerTests extends BaseTest {
Assertions.assertEquals(Arrays.asList("connect", "disconnect", "pub", "sub"), getScriptIdsByPlugId(plugin.getId())); Assertions.assertEquals(Arrays.asList("connect", "disconnect", "pub", "sub"), getScriptIdsByPlugId(plugin.getId()));
addPlugin = plugin; addPlugin = plugin;
// 模拟其他节点加载插件
pluginLoadService.handlePluginDeleteNotified(plugin.getId(), jarFile.getName());
pluginLoadService.handlePluginAddNotified(plugin.getId(), jarFile.getName());
// 增加覆盖率
pluginLoadService.handlePluginDeleteNotified(plugin.getId(), jarFile.getName());
pluginLoadService.loadPlugin(jarFile.getName());
pluginLoadService.handlePluginDeleteNotified(plugin.getId(), jarFile.getName());
pluginLoadService.loadPlugins();
pluginLoadService.getExtensions(Platform.class);
// 增加覆盖率 // 增加覆盖率
this.requestGetWithOkAndReturn(DEFAULT_LIST); this.requestGetWithOkAndReturn(DEFAULT_LIST);
pluginScriptService.add(null, null); pluginScriptService.add(null, null);
@ -174,6 +194,14 @@ public class PluginControllerTests extends BaseTest {
// 清理掉 // 清理掉
this.requestGetWithOk(DEFAULT_DELETE, "cloud-quota-plugin"); this.requestGetWithOk(DEFAULT_DELETE, "cloud-quota-plugin");
try {
MockMultipartFile mockMultipartFile =
new MockMultipartFile(jarFile.getName(), jarFile.getName(), "jar", new FileInputStream("/d/d"));
pluginLoadService.uploadPlugin2Local(mockMultipartFile);
} catch (Exception e) {
}
// @@重名校验异常 // @@重名校验异常
// 校验插件名称重名 // 校验插件名称重名
assertErrorCode(this.requestMultipart(DEFAULT_ADD, assertErrorCode(this.requestMultipart(DEFAULT_ADD,
@ -392,6 +420,22 @@ public class PluginControllerTests extends BaseTest {
// 获取返回值 // 获取返回值
} }
@Test
@Order(8)
public void testLocalFileRepository() throws Exception {
// 增加覆盖率
MockMultipartFile mockMultipartFile =
new MockMultipartFile("test file", "test file", "jar",
new FileInputStream(this.getClass().getClassLoader().getResource("file/my-driver-1.0.jar").getPath()));
localFileRepository.saveFile(mockMultipartFile, null);
try {
localFileRepository.downloadFile(null, null);
} catch (UnsupportedOperationException e) {
}
localFileRepository.getFolderFileNames(new FileRequest());
}
private void requestPostTest(String url, Object param) throws Exception { private void requestPostTest(String url, Object param) throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post(url) mockMvc.perform(MockMvcRequestBuilders.post(url)
.header(SessionConstants.HEADER_TOKEN, sessionId) .header(SessionConstants.HEADER_TOKEN, sessionId)