refactor(项目管理): 优化文件管理批量下载

This commit is contained in:
song-tianyang 2023-12-07 17:26:30 +08:00 committed by 刘瑞斌
parent 94c76c6d95
commit 0ff439f776
5 changed files with 85 additions and 10 deletions

View File

@ -227,7 +227,7 @@ public class EnvironmentService {
} }
} }
} }
return FileDownloadUtils.listBytesToZip(files); return FileDownloadUtils.listFileBytesToZip(files);
} }
public List<EnvironmentRequest> exportEnv(EnvironmentExportRequest environmentExportRequest) { public List<EnvironmentRequest> exportEnv(EnvironmentExportRequest environmentExportRequest) {

View File

@ -44,7 +44,11 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.unit.DataSize; import org.springframework.util.unit.DataSize;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.*; import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -235,7 +239,7 @@ public class FileMetadataService {
return fileMetadata.getId(); return fileMetadata.getId();
} }
private String genTransferFileName(String fullFileName, String projectId) { public String genTransferFileName(String fullFileName, String projectId) {
if (StringUtils.containsAny(fullFileName, "/")) { if (StringUtils.containsAny(fullFileName, "/")) {
throw new MSException(Translator.get("file.name.error")); throw new MSException(Translator.get("file.name.error"));
} }
@ -293,6 +297,20 @@ public class FileMetadataService {
return fileService.upload(file, uploadFileRequest); return fileService.upload(file, uploadFileRequest);
} }
public File getTmpFile(FileMetadata fileMetadata) {
File file = null;
if (TempFileUtils.isImgTmpFileExists(fileMetadata.getId())) {
file = new File(TempFileUtils.getTmpFilePath(fileMetadata.getId()));
} else {
try {
String filePath = TempFileUtils.createFile(TempFileUtils.getTmpFilePath(fileMetadata.getId()), this.getFile(fileMetadata));
file = new File(filePath);
} catch (Exception ignore) {
}
}
return file;
}
public byte[] getFileByte(FileMetadata fileMetadata) { public byte[] getFileByte(FileMetadata fileMetadata) {
String filePath = null; String filePath = null;
if (TempFileUtils.isImgTmpFileExists(fileMetadata.getId())) { if (TempFileUtils.isImgTmpFileExists(fileMetadata.getId())) {
@ -400,12 +418,9 @@ public class FileMetadataService {
} }
public byte[] batchDownload(List<FileMetadata> fileMetadataList) { public byte[] batchDownload(List<FileMetadata> fileMetadataList) {
Map<String, byte[]> files = new LinkedHashMap<>(); Map<String, File> fileMap = new HashMap<>();
fileMetadataList.forEach(fileMetadata -> { fileMetadataList.forEach(fileMetadata -> fileMap.put(this.getFileName(fileMetadata.getName(), fileMetadata.getType()), this.getTmpFile(fileMetadata)));
byte[] bytes = this.getFileByte(fileMetadata); return FileDownloadUtils.listBytesToZip(fileMap);
files.put(this.getFileName(fileMetadata.getName(), fileMetadata.getType()), bytes);
});
return FileDownloadUtils.listBytesToZip(files);
} }
//检查下载的文件的大小 //检查下载的文件的大小

View File

@ -73,6 +73,7 @@ public class FileModuleService extends ModuleTreeService implements CleanupProje
fileModule.setCreateUser(operator); fileModule.setCreateUser(operator);
fileModule.setUpdateUser(operator); fileModule.setUpdateUser(operator);
fileModule.setModuleType(ModuleConstants.NODE_TYPE_DEFAULT); fileModule.setModuleType(ModuleConstants.NODE_TYPE_DEFAULT);
fileModuleMapper.insert(fileModule); fileModuleMapper.insert(fileModule);
//记录日志 //记录日志

View File

@ -1,12 +1,46 @@
package io.metersphere.project.utils; package io.metersphere.project.utils;
import io.metersphere.sdk.util.LogUtils;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Map; import java.util.Map;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
public class FileDownloadUtils { public class FileDownloadUtils {
public static byte[] listBytesToZip(Map<String, byte[]> mapReport) {
public static byte[] listBytesToZip(Map<String, File> fileMap) {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
for (Map.Entry<String, File> fileEntry : fileMap.entrySet()) {
String fileName = fileEntry.getKey();
File file = fileEntry.getValue();
if (file.exists()) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
ZipEntry zipEntry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(zipEntry);
byte[] buffer = new byte[1024];
int num;
while ((num = bis.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, num);
}
zipOutputStream.closeEntry();
} catch (Exception ignore) {
}
}
}
zipOutputStream.close();
return byteArrayOutputStream.toByteArray();
} catch (Exception e) {
LogUtils.error(e);
return new byte[0];
}
}
public static byte[] listFileBytesToZip(Map<String, byte[]> mapReport) {
try { try {
if (!mapReport.isEmpty()) { if (!mapReport.isEmpty()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();

View File

@ -11,6 +11,7 @@ import io.metersphere.project.mapper.FileAssociationMapper;
import io.metersphere.project.mapper.FileMetadataMapper; import io.metersphere.project.mapper.FileMetadataMapper;
import io.metersphere.project.mapper.FileModuleMapper; import io.metersphere.project.mapper.FileModuleMapper;
import io.metersphere.project.service.FileAssociationService; import io.metersphere.project.service.FileAssociationService;
import io.metersphere.project.service.FileMetadataService;
import io.metersphere.project.service.FileModuleService; import io.metersphere.project.service.FileModuleService;
import io.metersphere.project.service.FileService; import io.metersphere.project.service.FileService;
import io.metersphere.project.utils.FileManagementBaseUtils; import io.metersphere.project.utils.FileManagementBaseUtils;
@ -90,6 +91,8 @@ public class FileManagementControllerTests extends BaseTest {
@Resource @Resource
private FileMetadataMapper fileMetadataMapper; private FileMetadataMapper fileMetadataMapper;
@Resource @Resource
private FileMetadataService fileMetadataService;
@Resource
private CommonProjectService commonProjectService; private CommonProjectService commonProjectService;
@BeforeEach @BeforeEach
@ -860,6 +863,11 @@ public class FileManagementControllerTests extends BaseTest {
fileBytes = mvcResult.getResponse().getContentAsByteArray(); fileBytes = mvcResult.getResponse().getContentAsByteArray();
Assertions.assertTrue(fileBytes.length > 0); Assertions.assertTrue(fileBytes.length > 0);
//重新下载全部文件
mvcResult = this.requestPostDownloadFile(FileManagementRequestUtils.URL_FILE_BATCH_DOWNLOAD, null, batchProcessDTO);
fileBytes = mvcResult.getResponse().getContentAsByteArray();
Assertions.assertTrue(fileBytes.length > 0);
//全部文件大小超过默认配置(600M)的限制 事先存储20个大小为50M的数据过后删除 //全部文件大小超过默认配置(600M)的限制 事先存储20个大小为50M的数据过后删除
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
String id = "test_" + i; String id = "test_" + i;
@ -1632,6 +1640,23 @@ public class FileManagementControllerTests extends BaseTest {
error = true; error = true;
} }
Assertions.assertTrue(error); Assertions.assertTrue(error);
//文件名称非法
error = false;
try {
fileMetadataService.transferFile("", null, null, null, null);
} catch (Exception e) {
error = true;
}
Assertions.assertTrue(error);
error = false;
try {
fileMetadataService.genTransferFileName("testTransfer/File.jpg", null);
} catch (Exception e) {
error = true;
}
Assertions.assertTrue(error);
} }
public void associationDelete() { public void associationDelete() {