fix(计划报告): 测试计划报告富文本图片预览
This commit is contained in:
parent
e091b11766
commit
be4c69034f
|
@ -41,6 +41,8 @@ public class FilterChainUtils {
|
||||||
filterChainDefinitionMap.put("/review/functional/case/download/file/**", "anon");
|
filterChainDefinitionMap.put("/review/functional/case/download/file/**", "anon");
|
||||||
//缺陷管理富文本访问
|
//缺陷管理富文本访问
|
||||||
filterChainDefinitionMap.put("/bug/attachment/preview/md/**", "anon");
|
filterChainDefinitionMap.put("/bug/attachment/preview/md/**", "anon");
|
||||||
|
//计划报告富文本访问
|
||||||
|
filterChainDefinitionMap.put("/test-plan/report/preview/md/**", "anon");
|
||||||
|
|
||||||
filterChainDefinitionMap.put("/system/version/current", "anon");
|
filterChainDefinitionMap.put("/system/version/current", "anon");
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
@ -166,4 +167,10 @@ public class TestPlanReportController {
|
||||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tpr.create_time desc");
|
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "tpr.create_time desc");
|
||||||
return PageUtils.setPageInfo(page, testPlanReportService.planReportList(request));
|
return PageUtils.setPageInfo(page, testPlanReportService.planReportList(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "/preview/md/{projectId}/{fileId}/{compressed}")
|
||||||
|
@Operation(summary = "缺陷管理-富文本缩略图-预览")
|
||||||
|
public ResponseEntity<byte[]> previewMd(@PathVariable String projectId, @PathVariable String fileId, @PathVariable("compressed") boolean compressed) {
|
||||||
|
return testPlanReportService.previewMd(projectId, fileId, compressed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,8 @@ import io.metersphere.plan.utils.CountUtils;
|
||||||
import io.metersphere.plan.utils.ModuleTreeUtils;
|
import io.metersphere.plan.utils.ModuleTreeUtils;
|
||||||
import io.metersphere.plan.utils.RateCalculateUtils;
|
import io.metersphere.plan.utils.RateCalculateUtils;
|
||||||
import io.metersphere.plugin.platform.dto.SelectOption;
|
import io.metersphere.plugin.platform.dto.SelectOption;
|
||||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
import io.metersphere.project.service.FileService;
|
||||||
import io.metersphere.sdk.constants.ExecStatus;
|
import io.metersphere.sdk.constants.*;
|
||||||
import io.metersphere.sdk.constants.ReportStatus;
|
|
||||||
import io.metersphere.sdk.constants.TestPlanConstants;
|
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.file.FileCenter;
|
import io.metersphere.sdk.file.FileCenter;
|
||||||
import io.metersphere.sdk.file.FileCopyRequest;
|
import io.metersphere.sdk.file.FileCopyRequest;
|
||||||
|
@ -39,6 +37,9 @@ import org.apache.ibatis.session.ExecutorType;
|
||||||
import org.apache.ibatis.session.SqlSession;
|
import org.apache.ibatis.session.SqlSession;
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
import org.mybatis.spring.SqlSessionUtils;
|
import org.mybatis.spring.SqlSessionUtils;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -66,6 +67,10 @@ public class TestPlanReportService {
|
||||||
@Resource
|
@Resource
|
||||||
private ExtTestPlanReportMapper extTestPlanReportMapper;
|
private ExtTestPlanReportMapper extTestPlanReportMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
private FileService fileService;
|
||||||
|
@Resource
|
||||||
|
private TestPlanReportAttachmentMapper testPlanReportAttachmentMapper;
|
||||||
|
@Resource
|
||||||
private ExtTestPlanReportBugMapper extTestPlanReportBugMapper;
|
private ExtTestPlanReportBugMapper extTestPlanReportBugMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private ExtTestPlanReportFunctionalCaseMapper extTestPlanReportFunctionalCaseMapper;
|
private ExtTestPlanReportFunctionalCaseMapper extTestPlanReportFunctionalCaseMapper;
|
||||||
|
@ -90,8 +95,6 @@ public class TestPlanReportService {
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanReportBugMapper testPlanReportBugMapper;
|
private TestPlanReportBugMapper testPlanReportBugMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanReportAttachmentMapper testPlanReportAttachmentMapper;
|
|
||||||
@Resource
|
|
||||||
private BaseUserMapper baseUserMapper;
|
private BaseUserMapper baseUserMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanSendNoticeService testPlanSendNoticeService;
|
private TestPlanSendNoticeService testPlanSendNoticeService;
|
||||||
|
@ -993,7 +996,97 @@ public class TestPlanReportService {
|
||||||
return extTestPlanReportMapper.getPlanReportListById(request);
|
return extTestPlanReportMapper.getPlanReportListById(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ResponseEntity<byte[]> previewMd(String projectId, String fileId, boolean compressed) {
|
||||||
|
byte[] bytes;
|
||||||
|
String fileName;
|
||||||
|
TestPlanReportAttachmentExample example = new TestPlanReportAttachmentExample();
|
||||||
|
example.createCriteria().andFileIdEqualTo(fileId);
|
||||||
|
List<TestPlanReportAttachment> reportAttachments = testPlanReportAttachmentMapper.selectByExample(example);
|
||||||
|
if (CollectionUtils.isEmpty(reportAttachments)) {
|
||||||
|
//在临时文件获取
|
||||||
|
fileName = getTempFileNameByFileId(fileId);
|
||||||
|
bytes = getPreviewImg(fileName, fileId, compressed);
|
||||||
|
} else {
|
||||||
|
//在正式目录获取
|
||||||
|
TestPlanReportAttachment attachment = reportAttachments.get(0);
|
||||||
|
fileName = attachment.getFileName();
|
||||||
|
FileRequest fileRequest = buildPlanFileRequest(projectId, attachment.getTestPlanReportId(), attachment.getFileId(), attachment.getFileName());
|
||||||
|
try {
|
||||||
|
bytes = fileService.download(fileRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MSException("get file error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.contentType(MediaType.parseMediaType("application/octet-stream"))
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
|
||||||
|
.body(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
public void updateExecuteTimeAndStatus(String prepareReportId) {
|
public void updateExecuteTimeAndStatus(String prepareReportId) {
|
||||||
extTestPlanReportMapper.batchUpdateExecuteTimeAndStatus(System.currentTimeMillis(), Collections.singletonList(prepareReportId));
|
extTestPlanReportMapper.batchUpdateExecuteTimeAndStatus(System.currentTimeMillis(), Collections.singletonList(prepareReportId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建计划报告文件请求
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @param resourceId 资源ID
|
||||||
|
* @param fileId 文件ID
|
||||||
|
* @param fileName 文件名称
|
||||||
|
* @return 文件请求对象
|
||||||
|
*/
|
||||||
|
private FileRequest buildPlanFileRequest(String projectId, String resourceId, String fileId, String fileName) {
|
||||||
|
FileRequest fileRequest = new FileRequest();
|
||||||
|
fileRequest.setFolder(DefaultRepositoryDir.getPlanReportDir(projectId, resourceId) + "/" + fileId);
|
||||||
|
fileRequest.setFileName(StringUtils.isEmpty(fileName) ? null : fileName);
|
||||||
|
fileRequest.setStorage(StorageType.MINIO.name());
|
||||||
|
return fileRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getPreviewImg(String fileName, String fileId, boolean isCompressed) {
|
||||||
|
String systemTempDir;
|
||||||
|
if (isCompressed) {
|
||||||
|
systemTempDir = DefaultRepositoryDir.getSystemTempCompressDir();
|
||||||
|
} else {
|
||||||
|
systemTempDir = DefaultRepositoryDir.getSystemTempDir();
|
||||||
|
}
|
||||||
|
FileRequest previewRequest = new FileRequest();
|
||||||
|
previewRequest.setFileName(fileName);
|
||||||
|
previewRequest.setStorage(StorageType.MINIO.name());
|
||||||
|
previewRequest.setFolder(systemTempDir + "/" + fileId);
|
||||||
|
byte[] previewImg = null;
|
||||||
|
try {
|
||||||
|
previewImg = fileService.download(previewRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error("获取预览图失败:{}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previewImg == null || previewImg.length == 0) {
|
||||||
|
try {
|
||||||
|
if (isCompressed) {
|
||||||
|
previewImg = this.compressPicWithFileMetadata(fileName, fileId);
|
||||||
|
previewRequest.setFolder(DefaultRepositoryDir.getSystemTempCompressDir() + "/" + fileId);
|
||||||
|
fileService.upload(previewImg, previewRequest);
|
||||||
|
}
|
||||||
|
return previewImg;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error("获取预览图失败:{}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return previewImg;
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取文件并压缩的方法需要上锁,防止并发超过一定数量时内存溢出
|
||||||
|
private synchronized byte[] compressPicWithFileMetadata(String fileName, String fileId) throws Exception {
|
||||||
|
byte[] fileBytes = this.getFile(fileName, fileId);
|
||||||
|
return TempFileUtils.compressPic(fileBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getFile(String fileName, String fileId) throws Exception {
|
||||||
|
FileRequest fileRequest = new FileRequest();
|
||||||
|
fileRequest.setFileName(fileName);
|
||||||
|
fileRequest.setFolder(DefaultRepositoryDir.getSystemTempDir() + "/" + fileId);
|
||||||
|
fileRequest.setStorage(StorageType.MINIO.name());
|
||||||
|
return fileService.download(fileRequest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue