diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtFileContentMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtFileContentMapper.java new file mode 100644 index 0000000000..badbe41a23 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtFileContentMapper.java @@ -0,0 +1,15 @@ +package io.metersphere.base.mapper.ext; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.io.InputStream; + +public interface ExtFileContentMapper { + @Select(value = { + "SELECT file ", + "FROM file_content ", + "WHERE file_id = #{id, jdbcType=VARCHAR}" + }) + InputStream selectZipBytes(@Param("id") String id); +} diff --git a/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java b/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java index 828cd04e5a..5031c4e889 100644 --- a/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java +++ b/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java @@ -16,9 +16,6 @@ import io.metersphere.performance.controller.request.ReportRequest; import io.metersphere.performance.service.ReportService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -137,11 +134,7 @@ public class PerformanceReportController { } @GetMapping("/jtl/download/{reportId}") - public ResponseEntity downloadJtl(@PathVariable String reportId) { - byte[] bytes = reportService.downloadJtl(reportId); - return ResponseEntity.ok() - .contentType(MediaType.parseMediaType("application/octet-stream")) - .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + reportId + ".jtl\"") - .body(bytes); + public void downloadJtlZip(@PathVariable String reportId, HttpServletResponse response) { + reportService.downloadJtlZip(reportId, response); } } diff --git a/backend/src/main/java/io/metersphere/performance/service/ReportService.java b/backend/src/main/java/io/metersphere/performance/service/ReportService.java index f6e9d65882..d453cf6d1d 100644 --- a/backend/src/main/java/io/metersphere/performance/service/ReportService.java +++ b/backend/src/main/java/io/metersphere/performance/service/ReportService.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.*; +import io.metersphere.base.mapper.ext.ExtFileContentMapper; import io.metersphere.base.mapper.ext.ExtLoadTestReportMapper; import io.metersphere.commons.constants.PerformanceTestStatus; import io.metersphere.commons.constants.ReportKeys; @@ -23,11 +24,15 @@ import io.metersphere.performance.engine.EngineFactory; import io.metersphere.service.FileService; import io.metersphere.service.TestResourceService; import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -52,6 +57,8 @@ public class ReportService { private LoadTestReportDetailMapper loadTestReportDetailMapper; @Resource private FileService fileService; + @Resource + private SqlSessionFactory sqlSessionFactory; public List getRecentReportList(ReportRequest request) { List orders = new ArrayList<>(); @@ -284,11 +291,28 @@ public class ReportService { return JSON.parseArray(content, ChartsData.class); } - public byte[] downloadJtl(String reportId) { + /** + * 流下载 jtl zip + */ + public void downloadJtlZip(String reportId, HttpServletResponse response) { LoadTestReportWithBLOBs report = getReport(reportId); if (StringUtils.isBlank(report.getFileId())) { throw new RuntimeException(Translator.get("load_test_report_file_not_exist")); } - return fileService.loadFileAsBytes(report.getFileId()); + response.setHeader("Content-Disposition", "attachment;fileName=" + reportId + ".zip"); + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + ExtFileContentMapper mapper = sqlSession.getMapper(ExtFileContentMapper.class); + try (InputStream inputStream = mapper.selectZipBytes(report.getFileId())) { + ServletOutputStream outputStream = response.getOutputStream(); + byte[] buffer = new byte[1024 * 4]; + int read; + while ((read = inputStream.read(buffer)) > -1) { + outputStream.write(buffer, 0, read); + } + } catch (Exception e) { + LogUtil.error(e); + MSException.throwException(e); + } + } } } diff --git a/frontend/src/business/components/performance/report/PerformanceReportView.vue b/frontend/src/business/components/performance/report/PerformanceReportView.vue index 1257af30cd..13a512d91e 100644 --- a/frontend/src/business/components/performance/report/PerformanceReportView.vue +++ b/frontend/src/business/components/performance/report/PerformanceReportView.vue @@ -293,12 +293,12 @@ export default { }; this.result = this.$request(config).then(response => { const content = response.data; - const blob = new Blob([content]); + const blob = new Blob([content], {type: "application/octet-stream"}); if ("download" in document.createElement("a")) { // 非IE下载 // chrome/firefox let aTag = document.createElement('a'); - aTag.download = this.reportId + ".jtl"; + aTag.download = this.reportId + ".zip"; aTag.href = URL.createObjectURL(blob); aTag.click(); URL.revokeObjectURL(aTag.href)