diff --git a/api-test/backend/src/main/java/io/metersphere/commons/utils/HashTreeUtil.java b/api-test/backend/src/main/java/io/metersphere/commons/utils/HashTreeUtil.java index 7b6b13c007..1fdb28a3ad 100644 --- a/api-test/backend/src/main/java/io/metersphere/commons/utils/HashTreeUtil.java +++ b/api-test/backend/src/main/java/io/metersphere/commons/utils/HashTreeUtil.java @@ -9,7 +9,6 @@ import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; import io.metersphere.base.domain.FileMetadata; import io.metersphere.commons.constants.ElementConstants; -import io.metersphere.commons.constants.StorageConstants; import io.metersphere.dto.AttachmentBodyFile; import io.metersphere.dto.FileInfoDTO; import io.metersphere.dto.JmeterRunRequestDTO; @@ -243,22 +242,15 @@ public class HashTreeUtil { if (runRequest.getPool().isPool() || runRequest.getPool().isK8s()) { return; } - List downloadFileList = ApiFileUtil.getExecuteFile(runRequest.getHashTree(), runRequest.getReportId(), true); - - Map repositoryFileMap = new HashMap<>(); - for (AttachmentBodyFile bodyFile : downloadFileList) { - if (!StringUtils.equals(bodyFile.getFileStorage(), StorageConstants.LOCAL.name()) - && StringUtils.isNotBlank(bodyFile.getFileMetadataId())) { - repositoryFileMap.put(bodyFile.getFileMetadataId(), bodyFile.getName()); - } - } - - LoggerUtil.info("本次执行[" + runRequest.getReportId() + "]需要下载[" + repositoryFileMap.size() + "]个文件,开始下载......"); + List executeFileList = ApiFileUtil.getExecuteFile(runRequest.getHashTree(), runRequest.getReportId(), true); + LoggerUtil.info("本次执行[" + runRequest.getReportId() + "]共需要[" + executeFileList.size() + "]个文件。"); FileMetadataService fileMetadataService = CommonBeanFactory.getBean(FileMetadataService.class); if (fileMetadataService != null) { - fileMetadataService.downloadApiExecuteFilesByIds(repositoryFileMap.keySet()); + List downloadFileList = fileMetadataService.filterDownloadFileList(executeFileList); + LoggerUtil.info("本次执行[" + runRequest.getReportId() + "]需要下载[" + downloadFileList.size() + "]个文件。开始下载。。。"); + fileMetadataService.downloadByAttachmentBodyFileList(downloadFileList); } - LoggerUtil.info("本次执行[" + runRequest.getReportId() + "]需要下载[" + repositoryFileMap.size() + "]个文件,下载结束。"); + LoggerUtil.info("本次执行[" + runRequest.getReportId() + "]需要下载[" + executeFileList.size() + "]个文件,下载结束。"); } public static void downFile( diff --git a/api-test/backend/src/main/java/io/metersphere/service/ApiJMeterFileService.java b/api-test/backend/src/main/java/io/metersphere/service/ApiJMeterFileService.java index a57755ee71..70fef5c6b7 100644 --- a/api-test/backend/src/main/java/io/metersphere/service/ApiJMeterFileService.java +++ b/api-test/backend/src/main/java/io/metersphere/service/ApiJMeterFileService.java @@ -1,5 +1,6 @@ package io.metersphere.service; +import groovy.lang.Lazy; import io.metersphere.api.dto.BodyFileRequest; import io.metersphere.api.dto.EnvironmentType; import io.metersphere.api.dto.definition.request.ElementUtil; @@ -62,6 +63,9 @@ public class ApiJMeterFileService { private PluginMapper pluginMapper; @Resource private RedisTemplateService redisTemplateService; + @Lazy + @Resource + private TemporaryFileUtil temporaryFileUtil; // 接口测试 用例/接口 private static final List CASE_MODES = new ArrayList<>() {{ @@ -326,13 +330,12 @@ public class ApiJMeterFileService { LogUtil.info("开始下载执行报告为[" + request.getReportId() + "]的文件库文件。"); List gitFileList = fileMetadataService.downloadApiExecuteFilesByIds(remoteFileIdList); gitFileList.forEach(fileInfoDTO -> - files.put(StringUtils.join( - fileInfoDTO.getProjectId(), - File.separator, - fileInfoDTO.getFileLastUpdateTime(), - File.separator, - fileInfoDTO.getFileName() - ), fileInfoDTO.getFileByte())); + files.put( + StringUtils.join( + temporaryFileUtil.generateRelativeDir(fileInfoDTO.getProjectId(), fileInfoDTO.getId(), fileInfoDTO.getFileLastUpdateTime()), + File.separator, + fileInfoDTO.getFileName() + ), fileInfoDTO.getFileByte())); LogUtil.info("下载到执行报告为[" + request.getReportId() + "]的文件库文件。共下载到【" + gitFileList.size() + "】个"); } } diff --git a/framework/sdk-parent/jmeter/src/main/java/io/metersphere/utils/TemporaryFileUtil.java b/framework/sdk-parent/jmeter/src/main/java/io/metersphere/utils/TemporaryFileUtil.java index ef0e3e8992..c06a60f069 100644 --- a/framework/sdk-parent/jmeter/src/main/java/io/metersphere/utils/TemporaryFileUtil.java +++ b/framework/sdk-parent/jmeter/src/main/java/io/metersphere/utils/TemporaryFileUtil.java @@ -27,22 +27,42 @@ public class TemporaryFileUtil { + File.separator; } - public String generateFileDir(String folder, String fileMetadataId, long updateTime) { + public String generateLocalFileDir() { + return fileFolder + DEFAULT_FILE_FOLDER + File.separator; + } + + //生成执行文件的相对路径 + public String generateRelativeDir(String folder, String fileMetadataId, long updateTime) { if (StringUtils.isBlank(folder)) { folder = DEFAULT_FILE_FOLDER; } if (StringUtils.isBlank(fileMetadataId)) { - return fileFolder + folder + File.separator; + return folder + File.separator; } else { - String metadataIdFolder = fileFolder + folder + File.separator + fileMetadataId + File.separator; + String metadataIdFolder = folder + File.separator + fileMetadataId + File.separator; return updateTime == 0 ? metadataIdFolder : metadataIdFolder + updateTime + File.separator; } } + //生成执行文件的绝对路径 + public String generateFileDir(String folder, String fileMetadataId, long updateTime) { + return fileFolder + generateRelativeDir(folder, fileMetadataId, updateTime); + } + public String generateFilePath(String folder, String fileMetadataId, long updateTime, String fileName) { return generateFileDir(folder, fileMetadataId, updateTime) + fileName; } + public String generateLocalFilePath(String filePath) { + return generateLocalFileDir() + filePath; + } + + //node使用 判断local文件 + public File getLocalFile(String filePath) { + File file = new File(this.generateLocalFilePath(filePath)); + return file.exists() ? file : null; + } + public File getFile(String folder, String fileMetadataId, long updateTime, String fileName) { File file = new File(generateFilePath(folder, fileMetadataId, updateTime, fileName)); if (file.exists()) { diff --git a/framework/sdk-parent/sdk/src/main/java/io/metersphere/metadata/service/FileMetadataService.java b/framework/sdk-parent/sdk/src/main/java/io/metersphere/metadata/service/FileMetadataService.java index 01884c49b2..0a20e78f31 100644 --- a/framework/sdk-parent/sdk/src/main/java/io/metersphere/metadata/service/FileMetadataService.java +++ b/framework/sdk-parent/sdk/src/main/java/io/metersphere/metadata/service/FileMetadataService.java @@ -1,6 +1,7 @@ package io.metersphere.metadata.service; import com.alibaba.nacos.common.utils.ByteUtils; +import groovy.lang.Lazy; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.FileAssociationMapper; import io.metersphere.base.mapper.FileContentMapper; @@ -10,7 +11,11 @@ import io.metersphere.commons.constants.ApiTestConstants; import io.metersphere.commons.constants.FileModuleTypeConstants; import io.metersphere.commons.constants.StorageConstants; import io.metersphere.commons.exception.MSException; -import io.metersphere.commons.utils.*; +import io.metersphere.commons.utils.FileUtils; +import io.metersphere.commons.utils.JSON; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.commons.utils.SessionUtils; +import io.metersphere.dto.AttachmentBodyFile; import io.metersphere.dto.FileInfoDTO; import io.metersphere.i18n.Translator; import io.metersphere.log.utils.ReflexObjectUtil; @@ -53,6 +58,8 @@ public class FileMetadataService { @Resource private FileAssociationMapper fileAssociationMapper; + @Lazy + @Resource private TemporaryFileUtil temporaryFileUtil; public List create(FileMetadataCreateRequest fileMetadata, List files) { @@ -549,18 +556,31 @@ public class FileMetadataService { return fileMetadataList.stream().map(FileMetadata::getId).collect(Collectors.toList()); } + public List filterDownloadFileList(List attachmentBodyFileList) { + List downloadFileList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(attachmentBodyFileList)) { + //检查是否存在已下载的文件 + attachmentBodyFileList.forEach(fileMetadata -> { + if (!StringUtils.equals(fileMetadata.getFileStorage(), StorageConstants.LOCAL.name())) { + File file = temporaryFileUtil.getFile(fileMetadata.getProjectId(), fileMetadata.getFileMetadataId(), fileMetadata.getFileUpdateTime(), fileMetadata.getName()); + if (file == null) { + downloadFileList.add(fileMetadata); + LoggerUtil.info("文件【" + fileMetadata.getFileUpdateTime() + "_" + fileMetadata.getName() + "】在执行目录【" + fileMetadata.getProjectId() + "】未找到,需要下载"); + } + } + }); + } + return downloadFileList; + } + /** - * 接口测试执行时下载附件的方法。 + * 提供给Node下载附件时的方法。 * 该方法会优先判断是否存在已下载好的文件,避免多次执行造成多次下载的情况 * - * @param fileIdList + * @param fileIdList 要下载的文件ID集合 * @return */ public List downloadApiExecuteFilesByIds(Collection fileIdList) { - if (temporaryFileUtil == null) { - temporaryFileUtil = CommonBeanFactory.getBean(TemporaryFileUtil.class); - } - List fileInfoDTOList = new ArrayList<>(); if (CollectionUtils.isEmpty(fileIdList)) { return fileInfoDTOList; @@ -591,6 +611,23 @@ public class FileMetadataService { return fileInfoDTOList; } + public void downloadByAttachmentBodyFileList(List downloadFileList) { + + LogUtil.info(JSON.toJSONString(downloadFileList) + " 获取执行文件开始"); + List downloadFileRequest = new ArrayList<>(); + downloadFileList.forEach(attachmentBodyFile -> { + FileRequest request = this.genFileRequest(attachmentBodyFile); + downloadFileRequest.add(request); + }); + + List repositoryFileDTOList = fileManagerService.downloadFileBatch(downloadFileRequest); + //将文件存储到执行文件目录中,避免多次执行时触发多次下载 + if (CollectionUtils.isNotEmpty(repositoryFileDTOList)) { + repositoryFileDTOList.forEach(repositoryFile -> temporaryFileUtil.saveFileByParamCheck(repositoryFile.getProjectId(), repositoryFile.getId(), repositoryFile.getFileLastUpdateTime(), repositoryFile.getFileName(), repositoryFile.getFileByte())); + } + LogUtil.info(JSON.toJSONString(downloadFileList) + " 获取执行文件结束"); + } + public List downloadFileByIds(Collection fileIdList) { if (CollectionUtils.isEmpty(fileIdList)) { return new ArrayList<>(0); @@ -610,6 +647,27 @@ public class FileMetadataService { return repositoryFileDTOList; } + private FileRequest genFileRequest(AttachmentBodyFile attachmentBodyFile) { + if (attachmentBodyFile != null) { + FileRequest request = new FileRequest(attachmentBodyFile.getProjectId(), attachmentBodyFile.getName(), null); + request.setResourceId(attachmentBodyFile.getFileMetadataId()); + request.setPath(attachmentBodyFile.getFilePath()); + request.setStorage(attachmentBodyFile.getFileStorage()); + request.setUpdateTime(attachmentBodyFile.getFileUpdateTime()); + if (StringUtils.equals(attachmentBodyFile.getFileStorage(), StorageConstants.GIT.name())) { + try { + RemoteFileAttachInfo gitFileInfo = JSON.parseObject(attachmentBodyFile.getFileAttachInfoJson(), RemoteFileAttachInfo.class); + request.setFileAttachInfo(gitFileInfo); + } catch (Exception e) { + LogUtil.error("解析Git附加信息【" + attachmentBodyFile.getFileAttachInfoJson() + "】失败!", e); + } + } + return request; + } else { + return new FileRequest(); + } + } + private FileRequest genFileRequest(FileMetadataWithBLOBs fileMetadata) { if (fileMetadata != null) { FileRequest request = new FileRequest(fileMetadata.getProjectId(), fileMetadata.getName(), fileMetadata.getType());