多文件上传修改

This commit is contained in:
Captain.B 2020-03-19 18:53:41 +08:00
parent f0dcf4e364
commit 86113caae1
10 changed files with 175 additions and 109 deletions

View File

@ -1,5 +1,5 @@
package io.metersphere.commons.constants;
public enum FileType {
JMX
JMX, CSV
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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
}

View File

@ -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);
LoadTestFile loadTestFile = new LoadTestFile();
loadTestFile.setTestId(loadTest.getId());
loadTestFile.setFileId(fileMetadata.getId());
loadTestFileMapper.insert(loadTestFile);
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());
final FileMetadata fileMetadata = saveFile(file);
LoadTestFile loadTestFile = new LoadTestFile();
loadTestFile.setTestId(request.getId());
loadTestFile.setFileId(fileMetadata.getId());
loadTestFileMapper.insert(loadTestFile);
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) {

View File

@ -85,7 +85,7 @@
let testId = to.path.split('/')[4]; // find testId
if (testId) {
this.$get('/testplan/get/' + testId, response => {
if(response.data){
if (response.data) {
this.testPlan = response.data;
}
});
@ -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;
}

View File

@ -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: ByteKBMB
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: ByteKBMB
type: 'JMX',
lastModified: file.lastModified,
status: 'todo',
size: file.size + ' Bytes', /// todo: ByteKBMB
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>

View File

@ -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!",

View File

@ -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': "请先删除已存在的文件!",