From d0b7921ceea4d62d98e71e5cd28a882a9d3cebe2 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 22 Sep 2021 11:13:01 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96)=20=E5=9C=BA=E6=99=AF=E6=89=B9=E9=87=8F=E4=B8=8B?= =?UTF-8?q?=E8=BD=BDjmx=E6=89=93=E5=8C=85=E6=88=90=E4=B8=80=E4=B8=AAzip?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=20--bug=3D1006480=20--user=3D=E8=B5=B5?= =?UTF-8?q?=E5=8B=87=20=E3=80=90github#6012=E3=80=91=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=9C=BA=E6=99=AF=EF=BC=88jmeter=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=EF=BC=89=E5=AF=BC=E5=87=BA=E5=9C=BA=E6=99=AF=E6=95=B0?= =?UTF-8?q?=E9=87=8F=E4=B8=8D=E6=AD=A3=E7=A1=AE=20https://www.tapd.cn/5504?= =?UTF-8?q?9933/s/1048981?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAutomationController.java | 8 ++++-- .../api/service/ApiAutomationService.java | 25 +++++++++++++++++++ .../metersphere/commons/utils/FileUtils.java | 24 ++++++++++++++++++ .../automation/scenario/ApiScenarioList.vue | 23 ++++++++++------- 4 files changed, 69 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java index aa30a75425..e9eb8311c1 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -283,8 +283,12 @@ public class ApiAutomationController { @PostMapping(value = "/export/jmx") @RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_EXPORT_SCENARIO) @MsAuditLog(module = "api_automation", type = OperLogConstants.EXPORT, sourceId = "#request.id", title = "#request.name", project = "#request.projectId") - public List exportJmx(@RequestBody ApiScenarioBatchRequest request) { - return apiAutomationService.exportJmx(request); + public ResponseEntity downloadBodyFiles(@RequestBody ApiScenarioBatchRequest request) { + byte[] bytes = apiAutomationService.exportZip(request); + return ResponseEntity.ok() + .contentType(MediaType.parseMediaType("application/octet-stream")) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + "场景JMX文件集.zip") + .body(bytes); } } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 5856ed58d3..9db79fa024 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -66,6 +66,7 @@ import javax.annotation.Resource; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -145,6 +146,30 @@ public class ApiAutomationService { return list; } + public byte[] exportZip(ApiScenarioBatchRequest request) { + List apiScenarioWithBLOBs = getExportResult(request); + // 生成jmx + Map files = new LinkedHashMap<>(); + apiScenarioWithBLOBs.forEach(item -> { + if (StringUtils.isNotEmpty(item.getScenarioDefinition())) { + String jmx = generateJmx(item); + if (StringUtils.isNotEmpty(jmx)) { + ApiScenrioExportJmx scenrioExportJmx = new ApiScenrioExportJmx(item.getName(), apiTestService.updateJmxString(jmx, null, true).getXml()); + String fileName = item.getName() + ".jmx"; + String jmxStr = scenrioExportJmx.getJmx(); + files.put(fileName, jmxStr.getBytes(StandardCharsets.UTF_8)); + } + } + }); + if (CollectionUtils.isNotEmpty(apiScenarioWithBLOBs)) { + List names = apiScenarioWithBLOBs.stream().map(ApiScenarioWithBLOBs::getName).collect(Collectors.toList()); + request.setName(String.join(",", names)); + List ids = apiScenarioWithBLOBs.stream().map(ApiScenarioWithBLOBs::getId).collect(Collectors.toList()); + request.setId(JSON.toJSONString(ids)); + } + return FileUtils.listBytesToZip(files); + } + public List listAll(ApiScenarioBatchRequest request) { ServiceUtils.getSelectAllIds(request, request.getCondition(), (query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query)); diff --git a/backend/src/main/java/io/metersphere/commons/utils/FileUtils.java b/backend/src/main/java/io/metersphere/commons/utils/FileUtils.java index bd3ad17795..53910b4cbb 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/FileUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/FileUtils.java @@ -9,12 +9,36 @@ import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; public class FileUtils { public static final String BODY_FILE_DIR = "/opt/metersphere/data/body"; public static final String MD_IMAGE_DIR = "/opt/metersphere/data/image/markdown"; + public static byte[] listBytesToZip(Map mapReport) { + try { + if (!mapReport.isEmpty()) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ZipOutputStream zos = new ZipOutputStream(baos); + for (Map.Entry report : mapReport.entrySet()) { + ZipEntry entry = new ZipEntry(report.getKey()); + entry.setSize(report.getValue().length); + zos.putNextEntry(entry); + zos.write(report.getValue()); + } + zos.closeEntry(); + zos.close(); + return baos.toByteArray(); + } + } catch (Exception e) { + return new byte[10]; + } + return new byte[10]; + } + private static void create(List bodyUploadIds, List bodyFiles, String path) { String filePath = BODY_FILE_DIR; if (StringUtils.isNotEmpty(path)) { diff --git a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue index 4fd4eba358..e0fe3c8a41 100644 --- a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue +++ b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue @@ -210,6 +210,7 @@ import {API_SCENARIO_LIST, PROJECT_NAME, WORKSPACE_ID} from "../../../../../comm import EnvironmentSelect from "../../definition/components/environment/EnvironmentSelect"; import BatchMove from "../../../track/case/components/BatchMove"; import MsRunMode from "./common/RunMode"; +import axios from "axios"; import { getCustomTableHeader, getCustomTableWidth, getLastTableSortField, saveLastTableSortField @@ -848,6 +849,17 @@ export default { }); }); }, + fileDownload(url, param) { + axios.post(url, param, {responseType: 'blob'}) + .then(response => { + let link = document.createElement("a"); + link.href = window.URL.createObjectURL(new Blob([response.data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"})); + link.download = "场景JMX文件集.zip"; + this.result.loading = false; + link.click(); + }); + }, + exportJmx() { let param = {}; this.buildBatchParam(param); @@ -856,16 +868,9 @@ export default { return; } this.result.loading = true; - this.result = this.$post("/api/automation/export/jmx", param, response => { - this.result.loading = false; - let obj = response.data; - if (obj && obj.length > 0) { - obj.forEach(item => { - downloadFile(item.name + ".jmx", item.jmx); - }); - } - }); + this.fileDownload("/api/automation/export/jmx", param); }, + getConditions() { return this.condition; },