多文件上传修改
This commit is contained in:
parent
f0dcf4e364
commit
86113caae1
|
@ -1,5 +1,5 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum FileType {
|
||||
JMX
|
||||
JMX, CSV
|
||||
}
|
||||
|
|
|
@ -50,17 +50,17 @@ public class LoadTestController {
|
|||
@PostMapping(value = "/save", consumes = {"multipart/form-data"})
|
||||
public String save(
|
||||
@RequestPart("request") SaveTestPlanRequest request,
|
||||
@RequestPart(value = "file") MultipartFile file
|
||||
@RequestPart(value = "file") List<MultipartFile> files
|
||||
) {
|
||||
return loadTestService.save(request, file);
|
||||
return loadTestService.save(request, files);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/edit", consumes = {"multipart/form-data"})
|
||||
public String edit(
|
||||
@RequestPart("request") EditTestPlanRequest request,
|
||||
@RequestPart(value = "file", required = false) MultipartFile file
|
||||
@RequestPart(value = "file", required = false) List<MultipartFile> files
|
||||
) {
|
||||
return loadTestService.edit(request, file);
|
||||
return loadTestService.edit(request, files);
|
||||
}
|
||||
|
||||
@GetMapping("/get/{testId}")
|
||||
|
@ -89,7 +89,7 @@ public class LoadTestController {
|
|||
}
|
||||
|
||||
@GetMapping("/file/metadata/{testId}")
|
||||
public FileMetadata getFileMetadata(@PathVariable String testId) {
|
||||
public List<FileMetadata> getFileMetadata(@PathVariable String testId) {
|
||||
return fileService.getFileMetadataByTestId(testId);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,17 @@
|
|||
package io.metersphere.controller.request.testplan;
|
||||
|
||||
import io.metersphere.base.domain.FileMetadata;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EditTestPlanRequest extends TestPlanRequest {
|
||||
private List<FileMetadata> updatedFileList;
|
||||
|
||||
public List<FileMetadata> getUpdatedFileList() {
|
||||
return updatedFileList;
|
||||
}
|
||||
|
||||
public void setUpdatedFileList(List<FileMetadata> updatedFileList) {
|
||||
this.updatedFileList = updatedFileList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public class FileService {
|
|||
return fileContent.getFile();
|
||||
}
|
||||
|
||||
public FileMetadata getFileMetadataByTestId(String testId) {
|
||||
public List<FileMetadata> getFileMetadataByTestId(String testId) {
|
||||
LoadTestFileExample loadTestFileExample = new LoadTestFileExample();
|
||||
loadTestFileExample.createCriteria().andTestIdEqualTo(testId);
|
||||
final List<LoadTestFile> loadTestFiles = loadTestFileMapper.selectByExample(loadTestFileExample);
|
||||
|
@ -37,8 +37,10 @@ public class FileService {
|
|||
if (CollectionUtils.isEmpty(loadTestFiles)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fileMetadataMapper.selectByPrimaryKey(loadTestFiles.get(0).getFileId());
|
||||
List<String> fileIds = loadTestFiles.stream().map(LoadTestFile::getFileId).collect(Collectors.toList());
|
||||
FileMetadataExample example = new FileMetadataExample();
|
||||
example.createCriteria().andIdIn(fileIds);
|
||||
return fileMetadataMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
public FileMetadata getFucFileMetadataByTestId(String testId) {
|
||||
|
@ -74,4 +76,17 @@ public class FileService {
|
|||
fileContentMapper.deleteByExample(fileContentExample);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteFileByIds(List<String> ids) {
|
||||
if (CollectionUtils.isEmpty(ids)) {
|
||||
return;
|
||||
}
|
||||
FileMetadataExample example = new FileMetadataExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
fileMetadataMapper.deleteByExample(example);
|
||||
|
||||
FileContentExample example2 = new FileContentExample();
|
||||
example2.createCriteria().andFileIdIn(ids);
|
||||
fileContentMapper.deleteByExample(example2);
|
||||
}
|
||||
}
|
|
@ -138,39 +138,39 @@ public class FuctionalTestService {
|
|||
|
||||
public void run(RunTestPlanRequest request) {
|
||||
final FucTestWithBLOBs fucTest = fucTestMapper.selectByPrimaryKey(request.getId());
|
||||
if (fucTest == null) {
|
||||
MSException.throwException("无法运行测试,未找到测试:" + request.getId());
|
||||
}
|
||||
|
||||
final FileMetadata fileMetadata = fileService.getFileMetadataByTestId(request.getId());
|
||||
if (fileMetadata == null) {
|
||||
MSException.throwException("无法运行测试,无法获取测试文件元信息,测试ID:" + request.getId());
|
||||
}
|
||||
|
||||
final FileContent fileContent = fileService.getFileContent(fileMetadata.getId());
|
||||
if (fileContent == null) {
|
||||
MSException.throwException("无法运行测试,无法获取测试文件内容,测试ID:" + request.getId());
|
||||
}
|
||||
|
||||
System.out.println("开始运行:" + fucTest.getName());
|
||||
final Engine engine = EngineFactory.createEngine(fileMetadata.getType());
|
||||
if (engine == null) {
|
||||
MSException.throwException(String.format("无法运行测试,未识别测试文件类型,测试ID:%s,文件类型:%s",
|
||||
request.getId(),
|
||||
fileMetadata.getType()));
|
||||
}
|
||||
|
||||
boolean init = true;
|
||||
try {
|
||||
// init = engine.init(EngineFactory.createContext(fucTest, fileMetadata, fileContent));
|
||||
} catch (Exception e) {
|
||||
MSException.throwException(e);
|
||||
}
|
||||
if (!init) {
|
||||
MSException.throwException(String.format("无法运行测试,初始化运行环境失败,测试ID:%s", request.getId()));
|
||||
}
|
||||
|
||||
// engine.start();
|
||||
// if (fucTest == null) {
|
||||
// MSException.throwException("无法运行测试,未找到测试:" + request.getId());
|
||||
// }
|
||||
//
|
||||
// final List<FileMetadata> fileMetadataList = fileService.getFileMetadataByTestId(request.getId());
|
||||
// if (fileMetadataList == null) {
|
||||
// MSException.throwException("无法运行测试,无法获取测试文件元信息,测试ID:" + request.getId());
|
||||
// }
|
||||
//
|
||||
// final FileContent fileContent = fileService.getFileContent(fileMetadata.getId());
|
||||
// if (fileContent == null) {
|
||||
// MSException.throwException("无法运行测试,无法获取测试文件内容,测试ID:" + request.getId());
|
||||
// }
|
||||
//
|
||||
// System.out.println("开始运行:" + fucTest.getName());
|
||||
// final Engine engine = EngineFactory.createEngine(fileMetadata.getType());
|
||||
// if (engine == null) {
|
||||
// MSException.throwException(String.format("无法运行测试,未识别测试文件类型,测试ID:%s,文件类型:%s",
|
||||
// request.getId(),
|
||||
// fileMetadata.getType()));
|
||||
// }
|
||||
//
|
||||
// boolean init = true;
|
||||
// try {
|
||||
//// init = engine.init(EngineFactory.createContext(fucTest, fileMetadata, fileContent));
|
||||
// } catch (Exception e) {
|
||||
// MSException.throwException(e);
|
||||
// }
|
||||
// if (!init) {
|
||||
// MSException.throwException(String.format("无法运行测试,初始化运行环境失败,测试ID:%s", request.getId()));
|
||||
// }
|
||||
//
|
||||
//// engine.start();
|
||||
|
||||
/// todo:通过调用stop方法能够停止正在运行的engine,但是如果部署了多个backend实例,页面发送的停止请求如何定位到具体的engine
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import io.metersphere.base.mapper.LoadTestFileMapper;
|
|||
import io.metersphere.base.mapper.LoadTestMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtLoadTestMapper;
|
||||
import io.metersphere.commons.constants.EngineType;
|
||||
import io.metersphere.commons.constants.FileType;
|
||||
import io.metersphere.commons.constants.TestStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
|
@ -15,6 +16,8 @@ import io.metersphere.dto.LoadTestDTO;
|
|||
import io.metersphere.engine.Engine;
|
||||
import io.metersphere.engine.EngineFactory;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
@ -25,6 +28,7 @@ import java.io.IOException;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
@ -52,20 +56,18 @@ public class LoadTestService {
|
|||
fileService.deleteFileByTestId(request.getId());
|
||||
}
|
||||
|
||||
public String save(SaveTestPlanRequest request, MultipartFile file) {
|
||||
if (file == null) {
|
||||
public String save(SaveTestPlanRequest request, List<MultipartFile> files) {
|
||||
if (files == null) {
|
||||
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
|
||||
}
|
||||
|
||||
final FileMetadata fileMetadata = saveFile(file);
|
||||
|
||||
final LoadTestWithBLOBs loadTest = saveLoadTest(request);
|
||||
|
||||
files.forEach(file -> {
|
||||
final FileMetadata fileMetadata = saveFile(file);
|
||||
LoadTestFile loadTestFile = new LoadTestFile();
|
||||
loadTestFile.setTestId(loadTest.getId());
|
||||
loadTestFile.setFileId(fileMetadata.getId());
|
||||
loadTestFileMapper.insert(loadTestFile);
|
||||
|
||||
});
|
||||
return loadTest.getId();
|
||||
}
|
||||
|
||||
|
@ -98,7 +100,8 @@ public class LoadTestService {
|
|||
fileMetadata.setSize(file.getSize());
|
||||
fileMetadata.setCreateTime(System.currentTimeMillis());
|
||||
fileMetadata.setUpdateTime(System.currentTimeMillis());
|
||||
fileMetadata.setType("JMX");
|
||||
FileType fileType = getFileType(fileMetadata.getName());
|
||||
fileMetadata.setType(fileType.name());
|
||||
// TODO engine 选择
|
||||
fileMetadata.setEngine(EngineType.DOCKER.name());
|
||||
fileMetadataMapper.insert(fileMetadata);
|
||||
|
@ -115,15 +118,30 @@ public class LoadTestService {
|
|||
return fileMetadata;
|
||||
}
|
||||
|
||||
public String edit(EditTestPlanRequest request, MultipartFile file) {
|
||||
private FileType getFileType(String filename) {
|
||||
int s = filename.lastIndexOf(".") + 1;
|
||||
String type = filename.substring(s);
|
||||
return FileType.valueOf(type.toUpperCase());
|
||||
}
|
||||
|
||||
public String edit(EditTestPlanRequest request, List<MultipartFile> files) {
|
||||
// 新选择了一个文件,删除原来的文件
|
||||
if (file != null) {
|
||||
fileService.deleteFileByTestId(request.getId());
|
||||
if (files != null) {
|
||||
List<FileMetadata> updatedFiles = request.getUpdatedFileList();
|
||||
List<FileMetadata> originFiles = fileService.getFileMetadataByTestId(request.getId());
|
||||
List<String> updatedFileIds = updatedFiles.stream().map(FileMetadata::getId).collect(Collectors.toList());
|
||||
List<String> originFileIds = originFiles.stream().map(FileMetadata::getId).collect(Collectors.toList());
|
||||
// 相减
|
||||
List<String> deleteFileIds = ListUtils.subtract(originFileIds, updatedFileIds);
|
||||
fileService.deleteFileByIds(deleteFileIds);
|
||||
|
||||
files.forEach(file -> {
|
||||
final FileMetadata fileMetadata = saveFile(file);
|
||||
LoadTestFile loadTestFile = new LoadTestFile();
|
||||
loadTestFile.setTestId(request.getId());
|
||||
loadTestFile.setFileId(fileMetadata.getId());
|
||||
loadTestFileMapper.insert(loadTestFile);
|
||||
});
|
||||
}
|
||||
|
||||
final LoadTestWithBLOBs loadTest = loadTestMapper.selectByPrimaryKey(request.getId());
|
||||
|
@ -149,10 +167,14 @@ public class LoadTestService {
|
|||
MSException.throwException(Translator.get("run_load_test_not_found") + request.getId());
|
||||
}
|
||||
|
||||
final FileMetadata fileMetadata = fileService.getFileMetadataByTestId(request.getId());
|
||||
if (fileMetadata == null) {
|
||||
final List<FileMetadata> fileMetadataList = fileService.getFileMetadataByTestId(request.getId());
|
||||
if (CollectionUtils.isEmpty(fileMetadataList)) {
|
||||
MSException.throwException(Translator.get("run_load_test_file_not_found") + request.getId());
|
||||
}
|
||||
FileMetadata fileMetadata = fileMetadataList.stream().filter(f -> StringUtils.equalsIgnoreCase(f.getType(), "JMX"))
|
||||
.findFirst().orElseGet(() -> {
|
||||
throw new RuntimeException(Translator.get("run_load_test_file_not_found") + request.getId());
|
||||
});
|
||||
|
||||
final FileContent fileContent = fileService.getFileContent(fileMetadata.getId());
|
||||
if (fileContent == null) {
|
||||
|
|
|
@ -151,9 +151,13 @@
|
|||
let formData = new FormData();
|
||||
let url = this.testPlan.id ? this.editPath : this.savePath;
|
||||
|
||||
if (!this.testPlan.file.id) {
|
||||
formData.append("file", this.testPlan.file);
|
||||
if (this.$refs.basicConfig.uploadList.length > 0) {
|
||||
this.$refs.basicConfig.uploadList.forEach(f => {
|
||||
formData.append("file", f);
|
||||
});
|
||||
}
|
||||
// 基本配置
|
||||
this.testPlan.updatedFileList = this.$refs.basicConfig.updatedFileList();
|
||||
// 压力配置
|
||||
this.testPlan.loadConfiguration = JSON.stringify(this.$refs.pressureConfig.convertProperty());
|
||||
// 高级配置
|
||||
|
@ -199,12 +203,7 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!this.testPlan.file) {
|
||||
this.$message({
|
||||
message: this.$t('load_test.jmx_is_null'),
|
||||
type: 'error'
|
||||
});
|
||||
|
||||
if (!this.$refs.basicConfig.validConfig()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<template>
|
||||
<div v-loading="result.loading">
|
||||
<el-upload
|
||||
accept=".jmx"
|
||||
accept=".jmx,.csv"
|
||||
drag
|
||||
action=""
|
||||
:limit="1"
|
||||
:limit="5"
|
||||
multiple
|
||||
:show-file-list="false"
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="handleUpload"
|
||||
|
@ -32,13 +33,9 @@
|
|||
:label="$t('load_test.last_modify_time')">
|
||||
<template slot-scope="scope">
|
||||
<i class="el-icon-time"/>
|
||||
<span class="last-modified">{{ scope.row.lastModified | timestampFormatDate }}</span>
|
||||
<span class="last-modified">{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
:label="$t('load_test.file_status')">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('commons.operating')">
|
||||
<template slot-scope="scope">
|
||||
|
@ -66,6 +63,7 @@
|
|||
jmxDeletePath: '/testplan/file/delete',
|
||||
fileList: [],
|
||||
tableData: [],
|
||||
uploadList: [],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
@ -82,29 +80,20 @@
|
|||
},
|
||||
methods: {
|
||||
getFileMetadata(testPlan) {
|
||||
this.fileList = [];// 一个测试只有一个文件
|
||||
this.tableData = [];// 一个测试只有一个文件
|
||||
this.fileList = [];
|
||||
this.tableData = [];
|
||||
this.result = this.$get(this.getFileMetadataPath + "/" + testPlan.id, response => {
|
||||
let file = response.data;
|
||||
let files = response.data;
|
||||
|
||||
if (!file) {
|
||||
if (!files) {
|
||||
Message.error({message: this.$t('load_test.related_file_not_found'), showClose: true});
|
||||
return;
|
||||
}
|
||||
|
||||
this.testPlan.file = file;
|
||||
this.fileList.push({
|
||||
id: file.id,
|
||||
name: file.name
|
||||
});
|
||||
|
||||
this.tableData.push({
|
||||
id: file.id,
|
||||
name: file.name,
|
||||
size: file.size + 'Byte', /// todo: 按照大小显示Byte、KB、MB等
|
||||
type: 'JMX',
|
||||
lastModified: file.updateTime,
|
||||
status: 'todo',
|
||||
// deep copy
|
||||
this.fileList = JSON.parse(JSON.stringify(files));
|
||||
this.tableData = JSON.parse(JSON.stringify(files));
|
||||
this.tableData.map(f => {
|
||||
f.size = f.size + ' Bytes';
|
||||
});
|
||||
})
|
||||
},
|
||||
|
@ -114,18 +103,24 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
if (this.tableData.filter(f => f.name === file.name).length > 0) {
|
||||
this.$message.error(this.$t('load_test.delete_file'));
|
||||
return false;
|
||||
}
|
||||
|
||||
let type = file.name.substring(file.name.lastIndexOf(".") + 1);
|
||||
|
||||
this.tableData.push({
|
||||
name: file.name,
|
||||
size: file.size + 'Byte', /// todo: 按照大小显示Byte、KB、MB等
|
||||
type: 'JMX',
|
||||
lastModified: file.lastModified,
|
||||
status: 'todo',
|
||||
size: file.size + ' Bytes', /// todo: 按照大小显示Byte、KB、MB等
|
||||
type: type.toUpperCase(),
|
||||
updateTime: file.lastModified,
|
||||
});
|
||||
|
||||
return true;
|
||||
},
|
||||
handleUpload(uploadResources) {
|
||||
this.testPlan.file = uploadResources.file;
|
||||
this.uploadList.push(uploadResources.file);
|
||||
},
|
||||
handleDownload(file) {
|
||||
let data = {
|
||||
|
@ -158,7 +153,7 @@
|
|||
});
|
||||
},
|
||||
handleDelete(file, index) {
|
||||
this.$alert(this.$t('commons.delete_file_confirm') + file.name + "?", '', {
|
||||
this.$alert(this.$t('load_test.delete_file_confirm') + file.name + "?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
|
@ -170,7 +165,9 @@
|
|||
_handleDelete(file, index) {
|
||||
this.fileList.splice(index, 1);
|
||||
this.tableData.splice(index, 1);
|
||||
this.testPlan.file = null;
|
||||
//
|
||||
let i = this.uploadList.indexOf(file);
|
||||
this.uploadList.splice(i, 1);
|
||||
},
|
||||
handleExceed() {
|
||||
this.$message.error(this.$t('load_test.delete_file'));
|
||||
|
@ -179,6 +176,26 @@
|
|||
/// todo: 是否需要对文件内容和大小做限制
|
||||
return file.size > 0;
|
||||
},
|
||||
updatedFileList() {
|
||||
return this.fileList;// 表示修改了已经上传的文件列表
|
||||
},
|
||||
validConfig() {
|
||||
let newJmxNum = 0, oldJmxNum = 0;
|
||||
if (this.uploadList.length > 0) {
|
||||
newJmxNum = this.uploadList.filter(f => f.name.endsWith(".jmx")).length;
|
||||
}
|
||||
if (this.fileList.length > 0) {
|
||||
oldJmxNum = this.fileList.filter(f => f.name.endsWith(".jmx")).length;
|
||||
}
|
||||
if (newJmxNum + oldJmxNum !== 1) {
|
||||
this.$message({
|
||||
message: this.$t('load_test.jmx_is_null'),
|
||||
type: 'error'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -122,14 +122,14 @@ export default {
|
|||
'is_running': 'Test is running! ',
|
||||
'test_name_is_null': 'Test name cannot be empty! ',
|
||||
'project_is_null': 'Project cannot be empty! ',
|
||||
'jmx_is_null': 'JMX file cannot be empty! ',
|
||||
'jmx_is_null': 'Can only contain one JMX file',
|
||||
'file_name': 'File name',
|
||||
'file_size': 'File size',
|
||||
'file_type': 'File Type',
|
||||
'file_status': 'File Status',
|
||||
'last_modify_time': 'Modify time',
|
||||
'upload_tips': 'Drag files here, or <em> click to upload </em>',
|
||||
'upload_type': 'Only JMX files can be uploaded',
|
||||
'upload_type': 'Only JMX/CSV files can be uploaded',
|
||||
'related_file_not_found': "No related test file found!",
|
||||
'delete_file_confirm': 'Confirm delete file:',
|
||||
'delete_file': "Please delete an existing file first!",
|
||||
|
|
|
@ -122,14 +122,14 @@ export default {
|
|||
'is_running': '正在运行!',
|
||||
'test_name_is_null': '测试名称不能为空!',
|
||||
'project_is_null': '项目不能为空!',
|
||||
'jmx_is_null': 'JMX文件不能为空!',
|
||||
'jmx_is_null': '只能包含一个JMX文件!',
|
||||
'file_name': '文件名',
|
||||
'file_size': '文件大小',
|
||||
'file_type': '文件类型',
|
||||
'file_status': '文件状态',
|
||||
'last_modify_time': '修改时间',
|
||||
'upload_tips': '将文件拖到此处,或<em>点击上传</em>',
|
||||
'upload_type': '只能上传JMX文件',
|
||||
'upload_type': '只能上传JMX/CSV文件',
|
||||
'related_file_not_found': "未找到关联的测试文件!",
|
||||
'delete_file_confirm': '确认删除文件: ',
|
||||
'delete_file': "请先删除已存在的文件!",
|
||||
|
|
Loading…
Reference in New Issue