完成创建和编辑测试时文件保存相关逻辑

This commit is contained in:
haifeng414 2020-02-17 21:59:34 +08:00
parent e7bbfe074d
commit a30af57c28
13 changed files with 195 additions and 138 deletions

View File

@ -3,18 +3,18 @@ package io.metersphere.base.domain;
import java.io.Serializable;
public class FileContent implements Serializable {
private String id;
private String fileId;
private String file;
private static final long serialVersionUID = 1L;
public String getId() {
return id;
public String getFileId() {
return fileId;
}
public void setId(String id) {
this.id = id == null ? null : id.trim();
public void setFileId(String fileId) {
this.fileId = fileId == null ? null : fileId.trim();
}
public String getFile() {

View File

@ -104,73 +104,73 @@ public class FileContentExample {
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
public Criteria andFileIdIsNull() {
addCriterion("file_id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
public Criteria andFileIdIsNotNull() {
addCriterion("file_id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
public Criteria andFileIdEqualTo(String value) {
addCriterion("file_id =", value, "fileId");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
public Criteria andFileIdNotEqualTo(String value) {
addCriterion("file_id <>", value, "fileId");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
public Criteria andFileIdGreaterThan(String value) {
addCriterion("file_id >", value, "fileId");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
public Criteria andFileIdGreaterThanOrEqualTo(String value) {
addCriterion("file_id >=", value, "fileId");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
public Criteria andFileIdLessThan(String value) {
addCriterion("file_id <", value, "fileId");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
public Criteria andFileIdLessThanOrEqualTo(String value) {
addCriterion("file_id <=", value, "fileId");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
public Criteria andFileIdLike(String value) {
addCriterion("file_id like", value, "fileId");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
public Criteria andFileIdNotLike(String value) {
addCriterion("file_id not like", value, "fileId");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
public Criteria andFileIdIn(List<String> values) {
addCriterion("file_id in", values, "fileId");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
public Criteria andFileIdNotIn(List<String> values) {
addCriterion("file_id not in", values, "fileId");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
public Criteria andFileIdBetween(String value1, String value2) {
addCriterion("file_id between", value1, value2, "fileId");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
public Criteria andFileIdNotBetween(String value1, String value2) {
addCriterion("file_id not between", value1, value2, "fileId");
return (Criteria) this;
}
}

View File

@ -10,7 +10,7 @@ public interface FileContentMapper {
int deleteByExample(FileContentExample example);
int deleteByPrimaryKey(String id);
int deleteByPrimaryKey(String fileId);
int insert(FileContent record);
@ -20,7 +20,7 @@ public interface FileContentMapper {
List<FileContent> selectByExample(FileContentExample example);
FileContent selectByPrimaryKey(String id);
FileContent selectByPrimaryKey(String fileId);
int updateByExampleSelective(@Param("record") FileContent record, @Param("example") FileContentExample example);

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.base.mapper.FileContentMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.FileContent">
<id column="id" jdbcType="VARCHAR" property="id" />
<id column="file_id" jdbcType="VARCHAR" property="fileId" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.FileContent">
<result column="file" jdbcType="LONGVARCHAR" property="file" />
@ -66,7 +66,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id
file_id
</sql>
<sql id="Blob_Column_List">
file
@ -107,11 +107,11 @@
,
<include refid="Blob_Column_List" />
from file_content
where id = #{id,jdbcType=VARCHAR}
where file_id = #{fileId,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from file_content
where id = #{id,jdbcType=VARCHAR}
where file_id = #{fileId,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.FileContentExample">
delete from file_content
@ -120,22 +120,22 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.FileContent">
insert into file_content (id, file)
values (#{id,jdbcType=VARCHAR}, #{file,jdbcType=LONGVARCHAR})
insert into file_content (file_id, file)
values (#{fileId,jdbcType=VARCHAR}, #{file,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.FileContent">
insert into file_content
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
<if test="fileId != null">
file_id,
</if>
<if test="file != null">
file,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
<if test="fileId != null">
#{fileId,jdbcType=VARCHAR},
</if>
<if test="file != null">
#{file,jdbcType=LONGVARCHAR},
@ -151,8 +151,8 @@
<update id="updateByExampleSelective" parameterType="map">
update file_content
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
<if test="record.fileId != null">
file_id = #{record.fileId,jdbcType=VARCHAR},
</if>
<if test="record.file != null">
file = #{record.file,jdbcType=LONGVARCHAR},
@ -164,7 +164,7 @@
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update file_content
set id = #{record.id,jdbcType=VARCHAR},
set file_id = #{record.fileId,jdbcType=VARCHAR},
file = #{record.file,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -172,7 +172,7 @@
</update>
<update id="updateByExample" parameterType="map">
update file_content
set id = #{record.id,jdbcType=VARCHAR}
set file_id = #{record.fileId,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -184,11 +184,11 @@
file = #{file,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
where file_id = #{fileId,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.FileContent">
update file_content
set file = #{file,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
where file_id = #{fileId,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -2,12 +2,10 @@ package io.metersphere.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.FileMetadata;
import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager;
import io.metersphere.controller.request.testplan.DeleteTestPlanRequest;
import io.metersphere.controller.request.testplan.FileOperationRequest;
import io.metersphere.controller.request.testplan.QueryTestPlanRequest;
import io.metersphere.controller.request.testplan.SaveTestPlanRequest;
import io.metersphere.controller.request.testplan.*;
import io.metersphere.dto.LoadTestDTO;
import io.metersphere.service.FileService;
import io.metersphere.service.LoadTestService;
@ -18,8 +16,6 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@RestController
@ -39,28 +35,31 @@ public class LoadTestController {
@PostMapping(value = "/save", consumes = {"multipart/form-data"})
public void save(
@RequestPart("request") SaveTestPlanRequest request,
@RequestPart("file") MultipartFile file
@RequestPart(value = "file") MultipartFile file
) {
loadTestService.save(request, file);
}
@PostMapping(value = "/edit", consumes = {"multipart/form-data"})
public void edit(
@RequestPart("request") EditTestPlanRequest request,
@RequestPart(value = "file", required = false) MultipartFile file
) {
loadTestService.edit(request, file);
}
@PostMapping("/delete")
public void delete(@RequestBody DeleteTestPlanRequest request) {
loadTestService.delete(request);
}
@PostMapping("/file/upload")
public void uploadJmx(MultipartFile file) throws IOException {
fileService.upload(file.getOriginalFilename(), file);
}
@PostMapping("/file/delete")
public void deleteJmx(@RequestBody FileOperationRequest request) {
System.out.println(String.format("delete %s", request.getName()));
@GetMapping("/file/metadata/{testId}")
public FileMetadata getFileMetadata(@PathVariable String testId) {
return fileService.getFileMetadataByTestId(testId);
}
@PostMapping("/file/download")
public ResponseEntity<org.springframework.core.io.Resource> downloadJmx(@RequestBody FileOperationRequest fileOperationRequest, HttpServletResponse response) {
public ResponseEntity<org.springframework.core.io.Resource> downloadJmx(@RequestBody FileOperationRequest fileOperationRequest) {
org.springframework.core.io.Resource resource = fileService.loadFileAsResource(fileOperationRequest.getName());
return ResponseEntity.ok()

View File

@ -0,0 +1,4 @@
package io.metersphere.controller.request.testplan;
public class EditTestPlanRequest extends TestPlanRequest {
}

View File

@ -2,7 +2,6 @@ package io.metersphere.controller.request.testplan;
public class TestPlanRequest {
private String id;
private String fileId;
private String projectId;
private String name;
@ -15,14 +14,6 @@ public class TestPlanRequest {
this.id = id;
}
public String getFileId() {
return fileId;
}
public void setFileId(String fileId) {
this.fileId = fileId;
}
public String getProjectId() {
return projectId;
}

View File

@ -1,19 +1,32 @@
package io.metersphere.service;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.FileContentMapper;
import io.metersphere.base.mapper.FileMetadataMapper;
import io.metersphere.base.mapper.LoadTestFileMapper;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@Service
public class FileService {
@Resource
private FileMetadataMapper fileMetadataMapper;
@Resource
private LoadTestFileMapper loadTestFileMapper;
@Resource
private FileContentMapper fileContentMapper;
// 将上传的文件保存在内存方便测试
private Map<String, MultipartFile> fileMap = new ConcurrentHashMap<>();
@ -25,7 +38,7 @@ public class FileService {
fileMap.put(name, file);
}
public Resource loadFileAsResource(String name) {
public org.springframework.core.io.Resource loadFileAsResource(String name) {
final MultipartFile file = fileMap.get(name);
if (file != null) {
@ -38,4 +51,35 @@ public class FileService {
return null;
}
public FileMetadata getFileMetadataByTestId(String testId) {
LoadTestFileExample loadTestFileExample = new LoadTestFileExample();
loadTestFileExample.createCriteria().andTestIdEqualTo(testId);
final List<LoadTestFile> loadTestFiles = loadTestFileMapper.selectByExample(loadTestFileExample);
if (CollectionUtils.isEmpty(loadTestFiles)) {
return null;
}
return fileMetadataMapper.selectByPrimaryKey(loadTestFiles.get(0).getFileId());
}
public void deleteFileByTestId(String testId) {
LoadTestFileExample loadTestFileExample = new LoadTestFileExample();
loadTestFileExample.createCriteria().andTestIdEqualTo(testId);
final List<LoadTestFile> loadTestFiles = loadTestFileMapper.selectByExample(loadTestFileExample);
loadTestFileMapper.deleteByExample(loadTestFileExample);
if (!CollectionUtils.isEmpty(loadTestFiles)) {
final List<String> fileIds = loadTestFiles.stream().map(LoadTestFile::getFileId).collect(Collectors.toList());
FileMetadataExample fileMetadataExample = new FileMetadataExample();
fileMetadataExample.createCriteria().andIdIn(fileIds);
fileMetadataMapper.deleteByExample(fileMetadataExample);
FileContentExample fileContentExample = new FileContentExample();
fileContentExample.createCriteria().andFileIdIn(fileIds);
fileContentMapper.deleteByExample(fileContentExample);
}
}
}

View File

@ -7,6 +7,7 @@ import io.metersphere.commons.constants.LoadTestFileType;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.IOUtils;
import io.metersphere.controller.request.testplan.DeleteTestPlanRequest;
import io.metersphere.controller.request.testplan.EditTestPlanRequest;
import io.metersphere.controller.request.testplan.QueryTestPlanRequest;
import io.metersphere.controller.request.testplan.SaveTestPlanRequest;
import io.metersphere.dto.LoadTestDTO;
@ -38,6 +39,8 @@ public class LoadTestService {
private FileContentMapper fileContentMapper;
@Resource
private LoadTestFileMapper loadTestFileMapper;
@Resource
private FileService fileService;
// 测试模拟数据
@PostConstruct
@ -66,10 +69,9 @@ public class LoadTestService {
}
public void delete(DeleteTestPlanRequest request) {
LoadTestExample loadTestExample = new LoadTestExample();
loadTestExample.createCriteria().andIdEqualTo(request.getId());
loadTestMapper.deleteByPrimaryKey(request.getId());
loadTestMapper.deleteByExample(loadTestExample);
fileService.deleteFileByTestId(request.getId());
}
public void save(SaveTestPlanRequest request, MultipartFile file) {
@ -111,7 +113,7 @@ public class LoadTestService {
fileMetadataMapper.insert(fileMetadata);
FileContent fileContent = new FileContent();
fileContent.setId(fileMetadata.getId());
fileContent.setFileId(fileMetadata.getId());
try {
fileContent.setFile(IOUtils.toString(file.getInputStream(), StandardCharsets.UTF_8));
} catch (IOException e) {
@ -121,4 +123,28 @@ public class LoadTestService {
return fileMetadata;
}
public void edit(EditTestPlanRequest request, MultipartFile file) {
// 新选择了一个文件删除原来的文件
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);
}
final LoadTestWithBLOBs loadTest = loadTestMapper.selectByPrimaryKey(request.getId());
if (loadTest == null) {
MSException.throwException("无法编辑测试,未找到测试:" + request.getId());
} else {
loadTest.setName(request.getName());
loadTest.setProjectId(request.getProjectId());
loadTest.setUpdateTime(System.currentTimeMillis());
loadTest.setScenarioDefinition("todo");
loadTest.setDescription("todo");
loadTestMapper.updateByPrimaryKeySelective(loadTest);
}
}
}

View File

@ -20,13 +20,13 @@
<el-tabs v-model="active" type="border-card" :stretch="true">
<el-tab-pane label="基础配置">
<test-plan-basic-config v-on:change-test-plan="changeTestPlan"/>
<test-plan-basic-config :test-plan="testPlan"/>
</el-tab-pane>
<el-tab-pane label="压力配置">
<test-plan-pressure-config v-on:change-test-plan="changeTestPlan"/>
<test-plan-pressure-config/>
</el-tab-pane>
<el-tab-pane label="高级配置">
<test-plan-advanced-config v-on:change-test-plan="changeTestPlan"/>
<test-plan-advanced-config/>
</el-tab-pane>
</el-tabs>
</div>
@ -50,6 +50,7 @@
testPlan: {},
listProjectPath: "/project/listAll",
savePath: "/testplan/save",
editPath: "/testplan/edit",
projects: [],
active: '0',
tabs: [{
@ -77,9 +78,7 @@
listProjects() {
this.$get(this.listProjectPath).then(response => {
this.projects = response.data.data;
}).catch((response) => {
this.$message.error(response.message);
});
})
},
save() {
if (!this.validTestPlan()) {
@ -87,17 +86,22 @@
}
let formData = new FormData();
let url = this.testPlan.id ? this.editPath : this.savePath;
formData.append("file", this.testPlan.file);
if (!this.testPlan.file.id) {
formData.append("file", this.testPlan.file);
}
// filejson
let requestJson = JSON.stringify(this.testPlan, function (key, value) {return key === "file" ? undefined : value});
let requestJson = JSON.stringify(this.testPlan, function (key, value) {
return key === "file" ? undefined : value
});
formData.append('request', new Blob([requestJson], {
type: "application/json"
}));
let options = {
method: 'POST',
url: this.savePath,
url: url,
data: formData,
headers: {
'Content-Type': undefined
@ -127,10 +131,6 @@
cancel() {
this.$router.push({path: '/'})
},
changeTestPlan(updateFunc) {
updateFunc(this.testPlan);
window.console.log(this.testPlan);
},
validTestPlan() {
if (!this.testPlan.name) {
this.$message({

View File

@ -5,7 +5,7 @@
<template>
<div>
我是第三个子组件
<el-button @click="testChange()" type="text" size="small">修改TestPlan值</el-button>
<el-button type="text" size="small">修改TestPlan值</el-button>
</div>
</template>
@ -17,14 +17,6 @@
}
},
methods: {
testChange() {
this._changeTestPlan(function (testPlan) {
testPlan.advancedConfig = "2"
})
},
_changeTestPlan(updateTestPlanFunc) {
this.$emit('change-test-plan', updateTestPlanFunc);
},
}
}
</script>

View File

@ -3,11 +3,12 @@
<el-upload
accept=".jmx"
drag
action=""
:limit="1"
:show-file-list="false"
:action="jmxUploadPath"
:before-upload="beforeUpload"
:http-request="handleUpload"
:on-exceed="handleExceed"
:file-list="fileList">
<i class="el-icon-upload"/>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
@ -54,16 +55,42 @@
<script>
export default {
name: "TestPlanBasicConfig",
props: ["testPlan"],
data() {
return {
jmxUploadPath: '/testplan/file/upload',
getFileMetadataPath: "/testplan/file/metadata",
jmxDownloadPath: '/testplan/file/download',
jmxDeletePath: '/testplan/file/delete',
fileList: [],
tableData: [],
};
},
created() {
if (this.testPlan.id) {
this.getFileMetadata(this.testPlan)
}
},
methods: {
getFileMetadata(testPlan) {
this.$get(this.getFileMetadataPath + "/" + testPlan.id).then(response => {
let file = response.data.data;
this.testPlan.file = file;
this.fileList.push({
id: file.id,
name: file.name
});
this.tableData.push({
name: file.name,
size: file.size + 'Byte', /// todo: ByteKBMB
type: 'JMX',
lastModified: file.lastModified,
status: 'todo',
});
})
},
beforeUpload(file) {
if (!this.fileValidator(file)) {
/// todo:
@ -81,11 +108,7 @@
return true;
},
handleUpload(uploadResources) {
window.console.log(uploadResources);
this._changeTestPlan(function (testPlan) {
testPlan.file = uploadResources.file;
});
this.testPlan.file = uploadResources.file;
},
handleDownload(file) {
let data = {
@ -124,26 +147,12 @@
});
},
_handleDelete(file, index) {
let data = {
name: file.name
};
this.$post(this.jmxDeletePath, data).then(response => {
if (response.data.success) {
this.fileList.splice(index, 1);
this.tableData.splice(index, 1);
this.$message({
message: '删除成功!',
type: 'success'
});
} else {
this.$message.error(response.message);
}
});
this.fileList.splice(index, 1);
this.tableData.splice(index, 1);
this.testPlan.file = null;
},
_changeTestPlan(updateTestPlanFunc) {
this.$emit('change-test-plan', updateTestPlanFunc);
handleExceed() {
this.$message.error("请先删除已存在的文件!");
},
fileValidator(file) {
/// todo:

View File

@ -60,14 +60,6 @@
},
methods: {
testChange() {
this._changeTestPlan(function (testPlan) {
testPlan.pressureConifg = "1"
})
},
_changeTestPlan(updateTestPlanFunc) {
this.$emit('change-test-plan', updateTestPlanFunc);
},
}
}
</script>