feat(用例评审): 用例评审评论副文本文件上传
This commit is contained in:
parent
9da60bcca2
commit
2438618c0c
|
@ -1,10 +1,7 @@
|
||||||
package io.metersphere.functional.controller;
|
package io.metersphere.functional.controller;
|
||||||
|
|
||||||
import io.metersphere.functional.domain.FunctionalCaseAttachment;
|
import io.metersphere.functional.domain.FunctionalCaseAttachment;
|
||||||
import io.metersphere.functional.request.AttachmentTransferRequest;
|
import io.metersphere.functional.request.*;
|
||||||
import io.metersphere.functional.request.FunctionalCaseAssociationFileRequest;
|
|
||||||
import io.metersphere.functional.request.FunctionalCaseDeleteFileRequest;
|
|
||||||
import io.metersphere.functional.request.FunctionalCaseFileRequest;
|
|
||||||
import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
||||||
import io.metersphere.project.dto.filemanagement.FileAssociationDTO;
|
import io.metersphere.project.dto.filemanagement.FileAssociationDTO;
|
||||||
import io.metersphere.project.dto.filemanagement.FileLogRecord;
|
import io.metersphere.project.dto.filemanagement.FileLogRecord;
|
||||||
|
@ -13,7 +10,6 @@ import io.metersphere.project.dto.filemanagement.response.FileInformationRespons
|
||||||
import io.metersphere.project.service.FileAssociationService;
|
import io.metersphere.project.service.FileAssociationService;
|
||||||
import io.metersphere.project.service.FileMetadataService;
|
import io.metersphere.project.service.FileMetadataService;
|
||||||
import io.metersphere.project.service.FileModuleService;
|
import io.metersphere.project.service.FileModuleService;
|
||||||
import io.metersphere.project.service.PermissionCheckService;
|
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
import io.metersphere.sdk.util.FileAssociationSourceUtil;
|
import io.metersphere.sdk.util.FileAssociationSourceUtil;
|
||||||
|
@ -26,6 +22,7 @@ import io.metersphere.system.utils.SessionUtils;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
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.http.ResponseEntity;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
@ -55,9 +52,6 @@ public class FunctionalCaseAttachmentController {
|
||||||
@Resource
|
@Resource
|
||||||
private FileModuleService fileModuleService;
|
private FileModuleService fileModuleService;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private PermissionCheckService permissionCheckService;
|
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/page")
|
@PostMapping("/page")
|
||||||
@Operation(summary = "用例管理-功能用例-附件-关联文件列表分页接口")
|
@Operation(summary = "用例管理-功能用例-附件-关联文件列表分页接口")
|
||||||
|
@ -87,7 +81,7 @@ public class FunctionalCaseAttachmentController {
|
||||||
@Operation(summary = "用例管理-功能用例-显示详情(副文本)图片缩略图")
|
@Operation(summary = "用例管理-功能用例-显示详情(副文本)图片缩略图")
|
||||||
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)
|
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)
|
||||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
public ResponseEntity<byte[]> compressedImg(@Validated @RequestBody FunctionalCaseFileRequest request) throws Exception {
|
public ResponseEntity<byte[]> compressedImg(@Validated @RequestBody FunctionalCaseSourceFileRequest request) throws Exception {
|
||||||
return functionalCaseAttachmentService.downloadPreviewCompressedImg(request);
|
return functionalCaseAttachmentService.downloadPreviewCompressedImg(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +180,7 @@ public class FunctionalCaseAttachmentController {
|
||||||
|
|
||||||
@PostMapping("/upload/temp/file")
|
@PostMapping("/upload/temp/file")
|
||||||
@Operation(summary = "用例管理-功能用例-上传副文本里所需的文件资源,并返回文件ID")
|
@Operation(summary = "用例管理-功能用例-上传副文本里所需的文件资源,并返回文件ID")
|
||||||
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_COMMENT)
|
@RequiresPermissions(logical = Logical.OR, value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_COMMENT})
|
||||||
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
|
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
|
||||||
return functionalCaseAttachmentService.uploadTemp(file);
|
return functionalCaseAttachmentService.uploadTemp(file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class FunctionalCaseReviewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/comment/{caseId}")
|
@GetMapping("/comment/{caseId}")
|
||||||
@Operation(summary = "用例管理-功能用例-评审-评论")
|
@Operation(summary = "用例管理-功能用例-评审-获取评审评论历史")
|
||||||
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)
|
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)
|
||||||
@CheckOwner(resourceId = "#caseId", resourceType = "functional_case")
|
@CheckOwner(resourceId = "#caseId", resourceType = "functional_case")
|
||||||
public List<CaseReviewHistoryDTO> getCaseReviewHistory(@PathVariable String caseId) {
|
public List<CaseReviewHistoryDTO> getCaseReviewHistory(@PathVariable String caseId) {
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package io.metersphere.functional.controller;
|
package io.metersphere.functional.controller;
|
||||||
|
|
||||||
import io.metersphere.functional.dto.CaseReviewHistoryDTO;
|
import io.metersphere.functional.dto.CaseReviewHistoryDTO;
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseFileRequest;
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseSourceFileRequest;
|
||||||
import io.metersphere.functional.request.ReviewFunctionalCaseRequest;
|
import io.metersphere.functional.request.ReviewFunctionalCaseRequest;
|
||||||
|
import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
||||||
import io.metersphere.functional.service.ReviewFunctionalCaseService;
|
import io.metersphere.functional.service.ReviewFunctionalCaseService;
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.system.security.CheckOwner;
|
import io.metersphere.system.security.CheckOwner;
|
||||||
|
@ -10,8 +13,10 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
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 java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -23,6 +28,9 @@ public class ReviewFunctionalCaseController {
|
||||||
@Resource
|
@Resource
|
||||||
private ReviewFunctionalCaseService reviewFunctionalCaseService;
|
private ReviewFunctionalCaseService reviewFunctionalCaseService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseAttachmentService functionalCaseAttachmentService;
|
||||||
|
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
@Operation(summary = "用例管理-用例评审-评审功能用例-提交评审")
|
@Operation(summary = "用例管理-用例评审-评审功能用例-提交评审")
|
||||||
@RequiresPermissions(PermissionConstants.CASE_REVIEW_REVIEW)
|
@RequiresPermissions(PermissionConstants.CASE_REVIEW_REVIEW)
|
||||||
|
@ -38,5 +46,36 @@ public class ReviewFunctionalCaseController {
|
||||||
return reviewFunctionalCaseService.getCaseReviewHistoryList(reviewId, caseId);
|
return reviewFunctionalCaseService.getCaseReviewHistoryList(reviewId, caseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/upload/temp/file")
|
||||||
|
@Operation(summary = "用例管理-用例评审-上传副文本里所需的文件资源,并返回文件ID")
|
||||||
|
@RequiresPermissions(PermissionConstants.CASE_REVIEW_REVIEW)
|
||||||
|
public String upload(@RequestParam("file") MultipartFile file) throws Exception {
|
||||||
|
return functionalCaseAttachmentService.uploadTemp(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/preview")
|
||||||
|
@Operation(summary = "用例管理-用例评审-附件/副文本(原图/文件)-文件预览")
|
||||||
|
@RequiresPermissions(PermissionConstants.CASE_REVIEW_REVIEW)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public ResponseEntity<byte[]> preview(@Validated @RequestBody FunctionalCaseFileRequest request) throws Exception {
|
||||||
|
return functionalCaseAttachmentService.downloadPreviewImgById(request);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/preview/compressed")
|
||||||
|
@Operation(summary = "用例管理-功能用例-显示详情(副文本)图片缩略图")
|
||||||
|
@RequiresPermissions(PermissionConstants.CASE_REVIEW_REVIEW)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public ResponseEntity<byte[]> compressedImg(@Validated @RequestBody FunctionalCaseSourceFileRequest request) throws Exception {
|
||||||
|
return functionalCaseAttachmentService.downloadPreviewCompressedImg(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/download")
|
||||||
|
@Operation(summary = "用例管理-功能用例-附件/副文本(原图/文件)-文件下载")
|
||||||
|
@RequiresPermissions(PermissionConstants.CASE_REVIEW_REVIEW)
|
||||||
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
|
public ResponseEntity<byte[]> download(@Validated @RequestBody FunctionalCaseFileRequest request) throws Exception {
|
||||||
|
return functionalCaseAttachmentService.downloadPreviewImgById(request);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class FunctionalCaseAttachmentDTO implements Serializable {
|
||||||
@Schema(description = "文件大小")
|
@Schema(description = "文件大小")
|
||||||
private Long size;
|
private Long size;
|
||||||
|
|
||||||
@Schema(description = "文件来源")
|
@Schema(description = "文件来源:附件(ATTACHMENT)/功能用例详情(CASE_DETAIL)/用例评论(CASE_COMMENT)/评审评论(REVIEW_COMMENT)")
|
||||||
private String fileSource;
|
private String fileSource;
|
||||||
|
|
||||||
@Schema(description = "是否本地")
|
@Schema(description = "是否本地")
|
||||||
|
|
|
@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class BatchReviewFunctionalCaseRequest extends BaseReviewCaseBatchRequest{
|
public class BatchReviewFunctionalCaseRequest extends BaseReviewCaseBatchRequest{
|
||||||
|
|
||||||
|
@ -21,4 +23,7 @@ public class BatchReviewFunctionalCaseRequest extends BaseReviewCaseBatchRequest
|
||||||
@Schema(description = "评论@的人的Id, 多个以';'隔开")
|
@Schema(description = "评论@的人的Id, 多个以';'隔开")
|
||||||
private String notifier;
|
private String notifier;
|
||||||
|
|
||||||
|
@Schema(description = "用例评审评论副文本的文件id集合")
|
||||||
|
private List<String> reviewCommentFileIds;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ public class FunctionalCaseAddRequest implements Serializable {
|
||||||
@Schema(description = "附件关联文件ID集合")
|
@Schema(description = "附件关联文件ID集合")
|
||||||
private List<String> relateFileMetaIds;
|
private List<String> relateFileMetaIds;
|
||||||
|
|
||||||
@Schema(description = "攻能用例详情(前置条件/步骤描述/预期结果/备注)上传的文件id集合")
|
@Schema(description = "功能用例详情(前置条件/步骤描述/预期结果/备注)上传的文件id集合")
|
||||||
private List<String> caseDetailFileIds;
|
private List<String> caseDetailFileIds;
|
||||||
|
|
||||||
@Schema(description = "评审id")
|
@Schema(description = "评审id")
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package io.metersphere.functional.request;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wx
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FunctionalCaseSourceFileRequest implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "项目id",requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@NotBlank(message = "{case_review.project_id.not_blank}")
|
||||||
|
private String projectId;
|
||||||
|
|
||||||
|
@Schema(description = "用例id",requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@NotBlank(message = "{case_review_functional_case.case_id.not_blank}")
|
||||||
|
private String caseId;
|
||||||
|
|
||||||
|
@Schema(description = "文件来源:附件(ATTACHMENT)/功能用例详情(CASE_DETAIL)/用例评论(CASE_COMMENT)/评审评论(REVIEW_COMMENT)")
|
||||||
|
@NotBlank(message = "{functional_case_source_file_request.file_source.not_blank}")
|
||||||
|
private String fileSource;
|
||||||
|
|
||||||
|
@Schema(description = "是否本地",requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Boolean local;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ReviewFunctionalCaseRequest {
|
public class ReviewFunctionalCaseRequest {
|
||||||
|
|
||||||
|
@ -32,4 +34,7 @@ public class ReviewFunctionalCaseRequest {
|
||||||
|
|
||||||
@Schema(description = "评论@的人的Id, 多个以';'隔开")
|
@Schema(description = "评论@的人的Id, 多个以';'隔开")
|
||||||
private String notifier;
|
private String notifier;
|
||||||
|
|
||||||
|
@Schema(description = "用例评审评论副文本的文件id集合")
|
||||||
|
private List<String> reviewCommentFileIds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.functional.service;
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.functional.constants.CaseEvent;
|
import io.metersphere.functional.constants.CaseEvent;
|
||||||
|
import io.metersphere.functional.constants.CaseFileSourceType;
|
||||||
import io.metersphere.functional.constants.CaseReviewPassRule;
|
import io.metersphere.functional.constants.CaseReviewPassRule;
|
||||||
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
|
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
|
||||||
import io.metersphere.functional.domain.*;
|
import io.metersphere.functional.domain.*;
|
||||||
|
@ -75,6 +76,8 @@ public class CaseReviewFunctionalCaseService extends ModuleTreeService {
|
||||||
private BaseCaseProvider provider;
|
private BaseCaseProvider provider;
|
||||||
@Resource
|
@Resource
|
||||||
private ReviewSendNoticeService reviewSendNoticeService;
|
private ReviewSendNoticeService reviewSendNoticeService;
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseAttachmentService functionalCaseAttachmentService;
|
||||||
|
|
||||||
|
|
||||||
private static final String CASE_MODULE_COUNT_ALL = "all";
|
private static final String CASE_MODULE_COUNT_ALL = "all";
|
||||||
|
@ -275,6 +278,11 @@ public class CaseReviewFunctionalCaseService extends ModuleTreeService {
|
||||||
List<CaseReviewFunctionalCaseUser> caseReviewFunctionalCaseUsers = caseReviewFunctionalCaseUserMapper.selectByExample(caseReviewFunctionalCaseUserExample);
|
List<CaseReviewFunctionalCaseUser> caseReviewFunctionalCaseUsers = caseReviewFunctionalCaseUserMapper.selectByExample(caseReviewFunctionalCaseUserExample);
|
||||||
Map<String, List<CaseReviewFunctionalCaseUser>> reviewerMap = caseReviewFunctionalCaseUsers.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCaseUser::getCaseId, Collectors.toList()));
|
Map<String, List<CaseReviewFunctionalCaseUser>> reviewerMap = caseReviewFunctionalCaseUsers.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCaseUser::getCaseId, Collectors.toList()));
|
||||||
|
|
||||||
|
FunctionalCaseExample functionalCaseExample = new FunctionalCaseExample();
|
||||||
|
functionalCaseExample.createCriteria().andIdIn(caseIds);
|
||||||
|
List<FunctionalCase> functionalCases = functionalCaseMapper.selectByExample(functionalCaseExample);
|
||||||
|
Map<String, String> caseProjectIdMap = functionalCases.stream().collect(Collectors.toMap(FunctionalCase::getId, FunctionalCase::getProjectId));
|
||||||
|
|
||||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||||
CaseReviewHistoryMapper caseReviewHistoryMapper = sqlSession.getMapper(CaseReviewHistoryMapper.class);
|
CaseReviewHistoryMapper caseReviewHistoryMapper = sqlSession.getMapper(CaseReviewHistoryMapper.class);
|
||||||
CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper = sqlSession.getMapper(CaseReviewFunctionalCaseMapper.class);
|
CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper = sqlSession.getMapper(CaseReviewFunctionalCaseMapper.class);
|
||||||
|
@ -307,6 +315,8 @@ public class CaseReviewFunctionalCaseService extends ModuleTreeService {
|
||||||
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.PASS.toString())) {
|
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.PASS.toString())) {
|
||||||
reviewSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_PASSED, reviewId);
|
reviewSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_PASSED, reviewId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functionalCaseAttachmentService.uploadMinioFile(caseId,caseProjectIdMap.get(caseId),request.getReviewCommentFileIds(),userId, CaseFileSourceType.REVIEW_COMMENT.toString());
|
||||||
}
|
}
|
||||||
sqlSession.flushStatements();
|
sqlSession.flushStatements();
|
||||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper;
|
||||||
import io.metersphere.functional.request.FunctionalCaseAssociationFileRequest;
|
import io.metersphere.functional.request.FunctionalCaseAssociationFileRequest;
|
||||||
import io.metersphere.functional.request.FunctionalCaseDeleteFileRequest;
|
import io.metersphere.functional.request.FunctionalCaseDeleteFileRequest;
|
||||||
import io.metersphere.functional.request.FunctionalCaseFileRequest;
|
import io.metersphere.functional.request.FunctionalCaseFileRequest;
|
||||||
|
import io.metersphere.functional.request.FunctionalCaseSourceFileRequest;
|
||||||
import io.metersphere.project.domain.FileAssociation;
|
import io.metersphere.project.domain.FileAssociation;
|
||||||
import io.metersphere.project.dto.filemanagement.FileInfo;
|
import io.metersphere.project.dto.filemanagement.FileInfo;
|
||||||
import io.metersphere.project.dto.filemanagement.FileLogRecord;
|
import io.metersphere.project.dto.filemanagement.FileLogRecord;
|
||||||
|
@ -286,9 +287,9 @@ public class FunctionalCaseAttachmentService {
|
||||||
*
|
*
|
||||||
* @param request request
|
* @param request request
|
||||||
*/
|
*/
|
||||||
public ResponseEntity<byte[]> downloadPreviewCompressedImg(FunctionalCaseFileRequest request) {
|
public ResponseEntity<byte[]> downloadPreviewCompressedImg(FunctionalCaseSourceFileRequest request) {
|
||||||
FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample();
|
FunctionalCaseAttachmentExample example = new FunctionalCaseAttachmentExample();
|
||||||
example.createCriteria().andFileIdEqualTo(request.getFileId()).andCaseIdEqualTo(request.getCaseId()).andFileSourceEqualTo(CaseFileSourceType.CASE_DETAIL.toString());
|
example.createCriteria().andCaseIdEqualTo(request.getCaseId()).andFileSourceEqualTo(CaseFileSourceType.CASE_DETAIL.toString());
|
||||||
List<FunctionalCaseAttachment> caseAttachments = functionalCaseAttachmentMapper.selectByExample(example);
|
List<FunctionalCaseAttachment> caseAttachments = functionalCaseAttachmentMapper.selectByExample(example);
|
||||||
if (CollectionUtils.isNotEmpty(caseAttachments)) {
|
if (CollectionUtils.isNotEmpty(caseAttachments)) {
|
||||||
FunctionalCaseAttachment attachment = caseAttachments.get(0);
|
FunctionalCaseAttachment attachment = caseAttachments.get(0);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.functional.service;
|
package io.metersphere.functional.service;
|
||||||
|
|
||||||
import io.metersphere.functional.constants.CaseEvent;
|
import io.metersphere.functional.constants.CaseEvent;
|
||||||
|
import io.metersphere.functional.constants.CaseFileSourceType;
|
||||||
import io.metersphere.functional.constants.CaseReviewPassRule;
|
import io.metersphere.functional.constants.CaseReviewPassRule;
|
||||||
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
|
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
|
||||||
import io.metersphere.functional.domain.CaseReviewFunctionalCaseUserExample;
|
import io.metersphere.functional.domain.CaseReviewFunctionalCaseUserExample;
|
||||||
|
@ -43,6 +44,8 @@ public class ReviewFunctionalCaseService {
|
||||||
private ReviewSendNoticeService reviewSendNoticeService;
|
private ReviewSendNoticeService reviewSendNoticeService;
|
||||||
@Resource
|
@Resource
|
||||||
private BaseCaseProvider provider;
|
private BaseCaseProvider provider;
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseAttachmentService functionalCaseAttachmentService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 评审功能用例
|
* 评审功能用例
|
||||||
|
@ -69,6 +72,9 @@ public class ReviewFunctionalCaseService {
|
||||||
extCaseReviewFunctionalCaseMapper.updateStatus(caseId, reviewId, functionalCaseStatus);
|
extCaseReviewFunctionalCaseMapper.updateStatus(caseId, reviewId, functionalCaseStatus);
|
||||||
caseReviewHistoryMapper.insert(caseReviewHistory);
|
caseReviewHistoryMapper.insert(caseReviewHistory);
|
||||||
|
|
||||||
|
//保存副文本评论附件
|
||||||
|
functionalCaseAttachmentService.uploadMinioFile(caseId,request.getProjectId(),request.getReviewCommentFileIds(),userId, CaseFileSourceType.REVIEW_COMMENT.toString());
|
||||||
|
|
||||||
//检查是否有@,发送@通知
|
//检查是否有@,发送@通知
|
||||||
if (StringUtils.isNotBlank(request.getNotifier())) {
|
if (StringUtils.isNotBlank(request.getNotifier())) {
|
||||||
List<String> relatedUsers = Arrays.asList(request.getNotifier().split(";"));
|
List<String> relatedUsers = Arrays.asList(request.getNotifier().split(";"));
|
||||||
|
|
|
@ -4,10 +4,7 @@ import io.metersphere.functional.constants.CaseFileSourceType;
|
||||||
import io.metersphere.functional.domain.FunctionalCaseAttachment;
|
import io.metersphere.functional.domain.FunctionalCaseAttachment;
|
||||||
import io.metersphere.functional.domain.FunctionalCaseAttachmentExample;
|
import io.metersphere.functional.domain.FunctionalCaseAttachmentExample;
|
||||||
import io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper;
|
import io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper;
|
||||||
import io.metersphere.functional.request.AttachmentTransferRequest;
|
import io.metersphere.functional.request.*;
|
||||||
import io.metersphere.functional.request.FunctionalCaseAssociationFileRequest;
|
|
||||||
import io.metersphere.functional.request.FunctionalCaseDeleteFileRequest;
|
|
||||||
import io.metersphere.functional.request.FunctionalCaseFileRequest;
|
|
||||||
import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
||||||
import io.metersphere.functional.utils.FileBaseUtils;
|
import io.metersphere.functional.utils.FileBaseUtils;
|
||||||
import io.metersphere.project.dto.filemanagement.request.FileMetadataTableRequest;
|
import io.metersphere.project.dto.filemanagement.request.FileMetadataTableRequest;
|
||||||
|
@ -248,10 +245,10 @@ public class FunctionalCaseAttachmentControllerTests extends BaseTest {
|
||||||
file = getNoNameMockMultipartFile();
|
file = getNoNameMockMultipartFile();
|
||||||
doUploadTempFileFalse(file);
|
doUploadTempFileFalse(file);
|
||||||
functionalCaseAttachmentService.uploadMinioFile("TEST_FUNCTIONAL_CASE_ATTACHMENT_ID_1","WX_TEST_PROJECT_ID", List.of(fileId),"admin", CaseFileSourceType.CASE_DETAIL.toString());
|
functionalCaseAttachmentService.uploadMinioFile("TEST_FUNCTIONAL_CASE_ATTACHMENT_ID_1","WX_TEST_PROJECT_ID", List.of(fileId),"admin", CaseFileSourceType.CASE_DETAIL.toString());
|
||||||
FunctionalCaseFileRequest request = new FunctionalCaseFileRequest();
|
FunctionalCaseSourceFileRequest request = new FunctionalCaseSourceFileRequest();
|
||||||
request.setProjectId("WX_TEST_PROJECT_ID");
|
request.setProjectId("WX_TEST_PROJECT_ID");
|
||||||
request.setLocal(true);
|
request.setLocal(true);
|
||||||
request.setFileId(fileId);
|
request.setFileSource(CaseFileSourceType.CASE_DETAIL.toString());
|
||||||
request.setCaseId("TEST_FUNCTIONAL_CASE_ATTACHMENT_ID_1");
|
request.setCaseId("TEST_FUNCTIONAL_CASE_ATTACHMENT_ID_1");
|
||||||
MvcResult mvcResult = this.downloadFile(ATTACHMENT_PREVIEW_COMPRESSED_URL, request);
|
MvcResult mvcResult = this.downloadFile(ATTACHMENT_PREVIEW_COMPRESSED_URL, request);
|
||||||
Assertions.assertNotNull(mvcResult);
|
Assertions.assertNotNull(mvcResult);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.functional.controller;
|
package io.metersphere.functional.controller;
|
||||||
|
|
||||||
|
import io.metersphere.functional.constants.CaseFileSourceType;
|
||||||
import io.metersphere.functional.constants.CaseReviewPassRule;
|
import io.metersphere.functional.constants.CaseReviewPassRule;
|
||||||
import io.metersphere.functional.constants.CaseReviewStatus;
|
import io.metersphere.functional.constants.CaseReviewStatus;
|
||||||
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
|
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
|
||||||
|
@ -8,27 +9,36 @@ import io.metersphere.functional.dto.CaseReviewHistoryDTO;
|
||||||
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseMapper;
|
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseMapper;
|
||||||
import io.metersphere.functional.mapper.CaseReviewHistoryMapper;
|
import io.metersphere.functional.mapper.CaseReviewHistoryMapper;
|
||||||
import io.metersphere.functional.mapper.CaseReviewMapper;
|
import io.metersphere.functional.mapper.CaseReviewMapper;
|
||||||
import io.metersphere.functional.request.BaseAssociateCaseRequest;
|
import io.metersphere.functional.mapper.FunctionalCaseAttachmentMapper;
|
||||||
import io.metersphere.functional.request.CaseReviewRequest;
|
import io.metersphere.functional.request.*;
|
||||||
import io.metersphere.functional.request.ReviewFunctionalCaseRequest;
|
import io.metersphere.functional.service.FunctionalCaseAttachmentService;
|
||||||
|
import io.metersphere.functional.utils.FileBaseUtils;
|
||||||
|
import io.metersphere.project.dto.filemanagement.request.FileUploadRequest;
|
||||||
|
import io.metersphere.project.service.FileMetadataService;
|
||||||
|
import io.metersphere.project.service.FileService;
|
||||||
|
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||||
import io.metersphere.sdk.constants.SessionConstants;
|
import io.metersphere.sdk.constants.SessionConstants;
|
||||||
|
import io.metersphere.sdk.constants.StorageType;
|
||||||
|
import io.metersphere.sdk.exception.MSException;
|
||||||
|
import io.metersphere.sdk.file.FileRequest;
|
||||||
import io.metersphere.sdk.util.JSON;
|
import io.metersphere.sdk.util.JSON;
|
||||||
import io.metersphere.system.base.BaseTest;
|
import io.metersphere.system.base.BaseTest;
|
||||||
import io.metersphere.system.controller.handler.ResultHolder;
|
import io.metersphere.system.controller.handler.ResultHolder;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.mock.web.MockMultipartFile;
|
||||||
import org.springframework.test.context.jdbc.Sql;
|
import org.springframework.test.context.jdbc.Sql;
|
||||||
import org.springframework.test.context.jdbc.SqlConfig;
|
import org.springframework.test.context.jdbc.SqlConfig;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
@ -44,13 +54,26 @@ public class ReviewFunctionalCaseControllerTests extends BaseTest {
|
||||||
private static final String ADD_CASE_REVIEW = "/case/review/add";
|
private static final String ADD_CASE_REVIEW = "/case/review/add";
|
||||||
private static final String REVIEW_LIST = "/review/functional/case/get/list/";
|
private static final String REVIEW_LIST = "/review/functional/case/get/list/";
|
||||||
|
|
||||||
|
public static final String ATTACHMENT_PREVIEW_COMPRESSED_URL = "/review/functional/case/preview/compressed";
|
||||||
|
public static final String ATTACHMENT_DOWNLOAD_URL = "/review/functional/case/download";
|
||||||
|
public static final String UPLOAD_TEMP = "/review/functional/case/upload/temp/file";
|
||||||
|
public static final String ATTACHMENT_PREVIEW_URL = "/review/functional/case/preview";
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CaseReviewMapper caseReviewMapper;
|
private CaseReviewMapper caseReviewMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private CaseReviewHistoryMapper caseReviewHistoryMapper;
|
private CaseReviewHistoryMapper caseReviewHistoryMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
|
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
|
||||||
|
@Resource
|
||||||
|
private FileService fileService;
|
||||||
|
@Resource
|
||||||
|
private FileMetadataService fileMetadataService;
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseAttachmentService functionalCaseAttachmentService;
|
||||||
|
@Resource
|
||||||
|
private FunctionalCaseAttachmentMapper functionalCaseAttachmentMapper;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(0)
|
@Order(0)
|
||||||
|
@ -250,6 +273,74 @@ public class ReviewFunctionalCaseControllerTests extends BaseTest {
|
||||||
System.out.println(JSON.toJSONString(gyqReviewCaseTest));
|
System.out.println(JSON.toJSONString(gyqReviewCaseTest));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(5)
|
||||||
|
public void testAttachmentPreview() throws Exception {
|
||||||
|
FunctionalCaseFileRequest request = new FunctionalCaseFileRequest();
|
||||||
|
request.setProjectId("project-review-case-test");
|
||||||
|
request.setLocal(true);
|
||||||
|
request.setFileId("TEST_REVIEW_COMMENT_FILE_ID");
|
||||||
|
request.setCaseId("gyqReviewCaseTest");
|
||||||
|
uploadLocalFile();
|
||||||
|
this.downloadFile(ATTACHMENT_PREVIEW_URL, request);
|
||||||
|
|
||||||
|
//覆盖controller
|
||||||
|
request.setLocal(false);
|
||||||
|
String fileId = uploadFile();
|
||||||
|
request.setFileId(fileId);
|
||||||
|
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||||
|
this.downloadFile(ATTACHMENT_PREVIEW_URL, request);
|
||||||
|
|
||||||
|
//增加覆盖率
|
||||||
|
request.setLocal(true);
|
||||||
|
request.setProjectId("123213");
|
||||||
|
request.setFileId("123123");
|
||||||
|
request.setCaseId("123123");
|
||||||
|
this.downloadFile(ATTACHMENT_PREVIEW_URL, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(6)
|
||||||
|
public void testUploadTemp() throws Exception {
|
||||||
|
//覆盖controller方法
|
||||||
|
MockMultipartFile file = getMockMultipartFile();
|
||||||
|
String fileId = doUploadTempFile(file);
|
||||||
|
Assertions.assertTrue(StringUtils.isNotBlank(fileId));
|
||||||
|
file = getNoNameMockMultipartFile();
|
||||||
|
doUploadTempFileFalse(file);
|
||||||
|
functionalCaseAttachmentService.uploadMinioFile("gyqReviewCaseTest","project-review-case-test", List.of(fileId),"admin", CaseFileSourceType.REVIEW_COMMENT.toString());
|
||||||
|
FunctionalCaseSourceFileRequest request = new FunctionalCaseSourceFileRequest();
|
||||||
|
request.setProjectId("project-review-case-test");
|
||||||
|
request.setLocal(true);
|
||||||
|
request.setFileSource(CaseFileSourceType.REVIEW_COMMENT.toString());
|
||||||
|
request.setCaseId("gyqReviewCaseTest");
|
||||||
|
MvcResult mvcResult = this.downloadFile(ATTACHMENT_PREVIEW_COMPRESSED_URL, request);
|
||||||
|
Assertions.assertNotNull(mvcResult);
|
||||||
|
FunctionalCaseAttachmentExample functionalCaseAttachmentExample = new FunctionalCaseAttachmentExample();
|
||||||
|
functionalCaseAttachmentExample.createCriteria().andCaseIdEqualTo("gyqReviewCaseTest").andFileIdEqualTo(fileId).andFileSourceEqualTo(CaseFileSourceType.REVIEW_COMMENT.toString());
|
||||||
|
List<FunctionalCaseAttachment> functionalCaseAttachments = functionalCaseAttachmentMapper.selectByExample(functionalCaseAttachmentExample);
|
||||||
|
Assertions.assertTrue(CollectionUtils.isNotEmpty(functionalCaseAttachments));
|
||||||
|
functionalCaseAttachmentService.uploadMinioFile("gyqReviewCaseTest","project-review-case-test",new ArrayList<>(),"admin", CaseFileSourceType.REVIEW_COMMENT.toString());
|
||||||
|
String functionalCaseDir = DefaultRepositoryDir.getFunctionalCaseDir("project-review-case-test", "gyqReviewCaseTest");
|
||||||
|
functionalCaseAttachmentService.uploadFileResource(functionalCaseDir,new HashMap<>(),"project-review-case-test", "gyqReviewCaseTest");
|
||||||
|
Map<String, String> objectObjectHashMap = new HashMap<>();
|
||||||
|
objectObjectHashMap.put(fileId,null);
|
||||||
|
functionalCaseAttachmentService.uploadFileResource(functionalCaseDir,objectObjectHashMap,"project-review-case-test", "gyqReviewCaseTest");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(7)
|
||||||
|
public void testAttachmentDownload() throws Exception {
|
||||||
|
//覆盖controller
|
||||||
|
FunctionalCaseFileRequest request = new FunctionalCaseFileRequest();
|
||||||
|
request.setProjectId("project-review-case-test");
|
||||||
|
request.setFileId("TEST_REVIEW_COMMENT_FILE_ID");
|
||||||
|
request.setCaseId("gyqReviewCaseTest");
|
||||||
|
request.setLocal(true);
|
||||||
|
this.downloadFile(ATTACHMENT_DOWNLOAD_URL, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<CaseReviewHistoryDTO> getCaseReviewHistoryList(String caseId,String reviewId) throws Exception {
|
public List<CaseReviewHistoryDTO> getCaseReviewHistoryList(String caseId,String reviewId) throws Exception {
|
||||||
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get(REVIEW_LIST +"/"+reviewId +"/"+ caseId).header(SessionConstants.HEADER_TOKEN, sessionId)
|
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get(REVIEW_LIST +"/"+reviewId +"/"+ caseId).header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||||
|
@ -289,5 +380,61 @@ public class ReviewFunctionalCaseControllerTests extends BaseTest {
|
||||||
return caseReviewMapper.selectByExample(caseReviewExample);
|
return caseReviewMapper.selectByExample(caseReviewExample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected MvcResult downloadFile(String url, Object param, Object... uriVariables) throws Exception {
|
||||||
|
return mockMvc.perform(getPostRequestBuilder(url, param, uriVariables))
|
||||||
|
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE))
|
||||||
|
.andExpect(status().isOk()).andReturn();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadLocalFile() {
|
||||||
|
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.JPG")).getPath();
|
||||||
|
MockMultipartFile file = new MockMultipartFile("file", "file_re-upload.JPG", MediaType.APPLICATION_OCTET_STREAM_VALUE, FileBaseUtils.getFileBytes(filePath));
|
||||||
|
FileRequest fileRequest = new FileRequest();
|
||||||
|
fileRequest.setFileName("测试评审");
|
||||||
|
fileRequest.setFolder(DefaultRepositoryDir.getFunctionalCaseDir("project-review-case-test", "gyqReviewCaseTest") + "/" + "TEST_REVIEW_COMMENT_FILE_ID");
|
||||||
|
fileRequest.setStorage(StorageType.MINIO.name());
|
||||||
|
try {
|
||||||
|
fileService.upload(file, fileRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MSException("save file error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String uploadFile() throws Exception {
|
||||||
|
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/test.JPG")).getPath();
|
||||||
|
MockMultipartFile file = new MockMultipartFile("file", "file_re-upload.JPG", MediaType.APPLICATION_OCTET_STREAM_VALUE, FileBaseUtils.getFileBytes(filePath));
|
||||||
|
FileUploadRequest fileUploadRequest = new FileUploadRequest();
|
||||||
|
fileUploadRequest.setProjectId("project-review-case-test");
|
||||||
|
return fileMetadataService.upload(fileUploadRequest, "admin", file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MockMultipartFile getMockMultipartFile() {
|
||||||
|
MockMultipartFile file = new MockMultipartFile(
|
||||||
|
"file",
|
||||||
|
"file_upload.JPG",
|
||||||
|
MediaType.APPLICATION_OCTET_STREAM_VALUE,
|
||||||
|
"Hello, World!".getBytes()
|
||||||
|
);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String doUploadTempFile(MockMultipartFile file) throws Exception {
|
||||||
|
return JSON.parseObject(requestUploadFileWithOkAndReturn(UPLOAD_TEMP, file)
|
||||||
|
.getResponse()
|
||||||
|
.getContentAsString(), ResultHolder.class)
|
||||||
|
.getData().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doUploadTempFileFalse(MockMultipartFile file) throws Exception {
|
||||||
|
this.requestUploadFile(UPLOAD_TEMP, file).andExpect(status().is5xxServerError());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MockMultipartFile getNoNameMockMultipartFile() {
|
||||||
|
MockMultipartFile file = new MockMultipartFile(
|
||||||
|
"file",
|
||||||
|
null,
|
||||||
|
MediaType.APPLICATION_OCTET_STREAM_VALUE,
|
||||||
|
"Hello, World!".getBytes()
|
||||||
|
);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue