From 23e187554324e1bdff896d7d18634711a7372755 Mon Sep 17 00:00:00 2001 From: fuliqi <fuliqi@qq.com> Date: 星期四, 12 十二月 2024 17:56:58 +0800 Subject: [PATCH] 项目库上传后端逻辑 --- common/src/main/java/com/ycl/common/utils/file/FileUploadUtils.java | 41 ++++++ common/src/main/java/com/ycl/common/utils/poi/ExcelUtil.java | 18 +++ business/src/main/java/com/ycl/listener/excel/ProjectImportListener.java | 142 +++++++++++++++++++++++ business/src/main/java/com/ycl/controller/ProjectInfoController.java | 16 ++ business/src/main/java/com/ycl/domain/entity/File.java | 2 business/src/main/java/com/ycl/service/impl/ProjectInfoServiceImpl.java | 130 +++++++++++++++++++++ business/src/main/java/com/ycl/service/ProjectInfoService.java | 3 7 files changed, 351 insertions(+), 1 deletions(-) diff --git a/business/src/main/java/com/ycl/controller/ProjectInfoController.java b/business/src/main/java/com/ycl/controller/ProjectInfoController.java index 963dfee..375f5ad 100644 --- a/business/src/main/java/com/ycl/controller/ProjectInfoController.java +++ b/business/src/main/java/com/ycl/controller/ProjectInfoController.java @@ -1,6 +1,7 @@ package com.ycl.controller; import com.ycl.common.base.Result; +import com.ycl.common.exception.base.BaseException; import com.ycl.common.group.Add; import com.ycl.common.group.Update; import com.ycl.common.utils.ProjectCodeGenerator; @@ -16,6 +17,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotEmpty; @@ -147,4 +149,18 @@ public Result updateUsedStatus(@PathVariable Integer id, @PathVariable Integer usedStatus) { return projectInfoService.updateUsedStatus(id, usedStatus); } + + /** + * 椤圭洰瀵煎叆 + * @param file + * @return + */ + @PostMapping("/import") + public Result importProject(@RequestPart("file") MultipartFile file) { + if (file.getSize() > 100 * 1024 * 1024) { + throw new BaseException("鏂囦欢杩囧ぇ锛屾枃浠朵笉寰楄秴杩�100MB"); + } + projectInfoService.importProject(file); + return Result.ok(); + } } diff --git a/business/src/main/java/com/ycl/domain/entity/File.java b/business/src/main/java/com/ycl/domain/entity/File.java index 806883c..718b9af 100644 --- a/business/src/main/java/com/ycl/domain/entity/File.java +++ b/business/src/main/java/com/ycl/domain/entity/File.java @@ -4,6 +4,7 @@ import com.ycl.common.enums.business.FileTypeEnum; import com.ycl.system.domain.base.AbsEntity; import lombok.Data; +import lombok.experimental.Accessors; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -16,6 +17,7 @@ */ @Data @TableName("t_file") +@Accessors(chain = true) public class File extends AbsEntity { private static final long serialVersionUID = 1L; diff --git a/business/src/main/java/com/ycl/listener/excel/ProjectImportListener.java b/business/src/main/java/com/ycl/listener/excel/ProjectImportListener.java new file mode 100644 index 0000000..b535353 --- /dev/null +++ b/business/src/main/java/com/ycl/listener/excel/ProjectImportListener.java @@ -0,0 +1,142 @@ +package com.ycl.listener.excel; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.ycl.common.exception.ServiceException; +import com.ycl.common.exception.base.BaseException; +import com.ycl.common.utils.excel.core.ExcelListener; +import com.ycl.common.utils.excel.core.ExcelResult; +import com.ycl.common.utils.spring.SpringUtils; +import com.ycl.domain.entity.*; +import com.ycl.domain.excel.ProjectExcelTemplate; +import com.ycl.service.ProjectInvestmentFundingService; +import com.ycl.service.ProjectInvestmentInfoService; +import com.ycl.service.ProjectInvestmentPolicyComplianceService; +import com.ycl.service.ProjectUnitRegistrationInfoService; +import com.ycl.service.impl.ProjectInfoServiceImpl; +import lombok.Data; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Data +//@NoArgsConstructor +public class ProjectImportListener extends AnalysisEventListener<ProjectExcelTemplate> implements ExcelListener<ProjectExcelTemplate> { + + + private final ProjectInfoServiceImpl projectInfoService; + private final ProjectInvestmentInfoService projectInvestmentInfoService; + private final ProjectInvestmentFundingService projectInvestmentFundingService; + private final ProjectUnitRegistrationInfoService projectUnitRegistrationInfoService; + private final ProjectInvestmentPolicyComplianceService projectPolicyComplianceService; + + private int successNum = 0; + private int failureNum = 0; + private final StringBuilder successMsg = new StringBuilder(); + private final StringBuilder failureMsg = new StringBuilder(); + private boolean hasData = false; + + private Map<String, Long> projectInfoMap = new HashMap<>(); + private Map<String, Long> investmentProjectPolicyComplianceMap = new HashMap<>(); + private Map<String, Long> documentsMap = new HashMap<>(); + + + public ProjectImportListener() { + this.projectInfoService = SpringUtils.getBean(ProjectInfoServiceImpl.class); + this.projectInvestmentInfoService = SpringUtils.getBean(ProjectInvestmentInfoService.class); + this.projectInvestmentFundingService = SpringUtils.getBean(ProjectInvestmentFundingService.class); + this.projectUnitRegistrationInfoService = SpringUtils.getBean(ProjectUnitRegistrationInfoService.class); + this.projectPolicyComplianceService = SpringUtils.getBean(ProjectInvestmentPolicyComplianceService.class); + + } + + @Override + public ExcelResult<ProjectExcelTemplate> getExcelResult() { + return new ExcelResult<>() { + + @Override + public String getAnalysis() { + if (failureNum > 0) { + failureMsg.insert(0, "寰堟姳姝夛紝瀵煎叆澶辫触锛佸叡 " + failureNum + " 鏉℃暟鎹牸寮忎笉姝g‘锛岄敊璇涓嬶細"); + throw new ServiceException(failureMsg.toString()); + } else { + successMsg.insert(0, "鎭枩鎮紝鏁版嵁宸插叏閮ㄥ鍏ユ垚鍔燂紒鍏� " + successNum + " 鏉★紝鏁版嵁濡備笅锛�"); + } + return successMsg.toString(); + } + + @Override + public List<ProjectExcelTemplate> getList() { + return null; + } + + @Override + public List<String> getErrorList() { + return null; + } + }; + } + + @Override + public void invoke(ProjectExcelTemplate projectExcelTemplate, AnalysisContext analysisContext) { + hasData = true; + //澶勭悊椤圭洰鍩虹淇℃伅 + ProjectInfo projectInfo = BeanUtil.toBean(projectExcelTemplate, ProjectInfo.class); + projectInfoService.checkProjectNameUnique(projectInfo); + projectInfoService.save(projectInfo); + //瀹℃壒璁″垝涔� + if (StrUtil.isNotBlank(projectExcelTemplate.getApprovalPlan())) { + String[] names = projectExcelTemplate.getApprovalPlan().split(","); + for (String name : names) { + projectInfoMap.put(name, projectInfo.getId()); + } + } + + //澶勭悊鎶曡祫绠$悊淇℃伅 + ProjectInvestmentInfo projectInvestmentInfo = BeanUtil.toBean(projectExcelTemplate, ProjectInvestmentInfo.class); + projectInvestmentInfo.setProjectId(projectInfo.getId()); + projectInvestmentInfoService.save(projectInvestmentInfo); + + //澶勭悊椤圭洰鎶曡祫鍙婅祫閲戞潵婧� + ProjectInvestmentFunding projectInvestmentFunding = BeanUtil.toBean(projectExcelTemplate, ProjectInvestmentFunding.class); + projectInvestmentFunding.setProjectId(projectInfo.getId()); + projectInvestmentFundingService.save(projectInvestmentFunding); + + // 澶勭悊椤圭洰娉曚汉鍗曚綅淇℃伅 + ProjectUnitRegistrationInfo projectUnitRegistrationInfo = BeanUtil.toBean(projectExcelTemplate, ProjectUnitRegistrationInfo.class); + projectUnitRegistrationInfo.setProjectId(projectInfo.getId()); + projectUnitRegistrationInfoService.save(projectUnitRegistrationInfo); + + //澶勭悊鎶曡祫浜т笟鏀跨瓥绗﹀悎鎯呭喌 + ProjectInvestmentPolicyCompliance investmentProjectPolicyCompliance = BeanUtil.toBean(projectExcelTemplate, ProjectInvestmentPolicyCompliance.class); + investmentProjectPolicyCompliance.setProjectId(projectInfo.getId()); + projectPolicyComplianceService.save(investmentProjectPolicyCompliance); + //绗﹀悎鏀跨瓥闄勪欢 + if (StrUtil.isNotBlank(projectExcelTemplate.getPolicyComplianceAttachment())) { + String[] names2 = projectExcelTemplate.getPolicyComplianceAttachment().split(","); + for (String name : names2) { + investmentProjectPolicyComplianceMap.put(name, investmentProjectPolicyCompliance.getId()); + } + } + + // 鐩稿叧鏂囦功 + if (StrUtil.isNotBlank(projectExcelTemplate.getDocuments())) { + String[] documentNames = projectExcelTemplate.getDocuments().split(","); + for (String name : documentNames) { + documentsMap.put(name, projectInfo.getId()); + } + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + if (!hasData) { + throw new BaseException("excel涓虹┖锛岃濉叆鏁版嵁鍚庡鍏�"); + } + } + + +} diff --git a/business/src/main/java/com/ycl/service/ProjectInfoService.java b/business/src/main/java/com/ycl/service/ProjectInfoService.java index 41fac95..5eee464 100644 --- a/business/src/main/java/com/ycl/service/ProjectInfoService.java +++ b/business/src/main/java/com/ycl/service/ProjectInfoService.java @@ -9,6 +9,7 @@ import com.ycl.domain.query.ProjectInfoQuery; import com.ycl.domain.vo.IndexCountVO; import com.ycl.domain.vo.IndexDTO; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -84,4 +85,6 @@ void export(HttpServletResponse response, ProjectExportQuery query) throws IOException; Result updateUsedStatus(Integer id, Integer usedStatus); + + void importProject(MultipartFile file); } diff --git a/business/src/main/java/com/ycl/service/impl/ProjectInfoServiceImpl.java b/business/src/main/java/com/ycl/service/impl/ProjectInfoServiceImpl.java index afe0041..0dd853d 100644 --- a/business/src/main/java/com/ycl/service/impl/ProjectInfoServiceImpl.java +++ b/business/src/main/java/com/ycl/service/impl/ProjectInfoServiceImpl.java @@ -2,11 +2,13 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.ZipUtil; import com.alibaba.excel.EasyExcel; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.common.base.Result; import com.ycl.common.config.SysConfig; @@ -21,6 +23,9 @@ import com.ycl.common.utils.StringUtils; import com.ycl.common.utils.bean.BeanUtils; import com.ycl.common.utils.excel.OutputExcelUtils; +import com.ycl.common.utils.file.FileUploadUtils; +import com.ycl.common.utils.file.FileUtils; +import com.ycl.common.utils.poi.ExcelUtil; import com.ycl.domain.entity.*; import com.ycl.domain.excel.ProjectExcelTemplate; import com.ycl.domain.form.DocumentInfoForm; @@ -30,6 +35,7 @@ import com.ycl.domain.query.ProjectInfoQuery; import com.ycl.domain.vo.*; import com.ycl.framework.utils.PageUtil; +import com.ycl.listener.excel.ProjectImportListener; import com.ycl.mapper.*; import com.ycl.service.FileService; import com.ycl.service.ProjectInfoService; @@ -38,20 +44,25 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import java.util.zip.ZipOutputStream; /** @@ -546,4 +557,123 @@ baseMapper.updateById(entity); return Result.ok("鍒犻櫎鎴愬姛"); } + + @Transactional + @Override + public void importProject(MultipartFile file) { + java.io.File tempZip = null; + java.io.File tempDir = null; + try { + tempZip = java.io.File.createTempFile("temp", ".zip"); + try(InputStream inputStream = file.getInputStream()) { + Files.copy(inputStream, tempZip.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + + tempDir = Files.createTempDirectory("temp-dir").toFile(); + ZipUtil.unzip(tempZip, tempDir, StandardCharsets.ISO_8859_1); + + Path path = tempDir.toPath(); + ProjectImportListener projectImportListener = new ProjectImportListener(); + //闇�瑕佸瓨鍏ユ暟鎹簱 + ArrayList<File> attachments = new ArrayList<>(); + //瀹為檯鐨勬枃浠� + List<java.io.File> files = new ArrayList<>(); + try (Stream<Path> pathStream = Files.walk(path)) { + pathStream.forEach(filePath -> { + if (Files.isDirectory(filePath) && filePath.getFileName().toString().equals("attachment")) { + //闄勪欢澶勭悊 + try (Stream<Path> stream = Files.walk(filePath)) { + stream.forEach(attachmentPath -> { + if (Files.isRegularFile(attachmentPath)) { + files.add(attachmentPath.toFile()); + } + }); + } catch (IOException e) { + log.error(e.getMessage()); + throw new RuntimeException(e); + } + } else if (Files.isRegularFile(filePath) && filePath.getFileName().toString().equals("excel.xlsx")) { + //瀵煎叆鏁版嵁澶勭悊 + try (FileInputStream fileInputStream = new FileInputStream(filePath.toFile())) { + ExcelUtil.importExcel(fileInputStream, ProjectExcelTemplate.class, projectImportListener); + } catch (IOException e) { + log.error(e.getMessage()); + throw new RuntimeException(e); + } + } + }); + } + /* 鎶婇檮浠跺瓨鍏ヤ笂浼犺矾寰� */ + //涓婁紶鏂囦欢璺緞 + String filePath = SysConfig.getUploadPath(); + files.forEach(attachmentFile -> { + try { + //涓婁紶 + String url = FileUploadUtils.upload(filePath, file); + //瀛樻斁鐨勬枃浠跺悕浼氬姞涓奯鏃堕棿鎴崇殑鍚庣紑 + String newName = FileUtils.getName(url); + attachments.add(new File() + .setUrl(url) + .setName(newName) + .setOriginalName(attachmentFile.getName())); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + Map<String, Long> projectInfoMap = projectImportListener.getProjectInfoMap(); + Map<String, Long> investmentProjectPolicyComplianceMap = projectImportListener.getInvestmentProjectPolicyComplianceMap(); + Map<String, Long> documentsMap = projectImportListener.getDocumentsMap(); + //琛ュ厖type鍜宐usId瀛楁 + attachments.forEach(attachment -> { + String fileName = attachment.getOriginalName(); + if (ObjectUtil.isNotNull(projectInfoMap.get(fileName))) { + attachment.setBusId(projectInfoMap.get(fileName)); + attachment.setType(FileTypeEnum.PROJECT_INFO); + } else if (ObjectUtil.isNotNull(investmentProjectPolicyComplianceMap.get(fileName))) { + attachment.setBusId(investmentProjectPolicyComplianceMap.get(fileName)); + attachment.setType(FileTypeEnum.INVEST_POLICY); + } else if (ObjectUtil.isNotNull(documentsMap.get(fileName))) { + attachment.setBusId(documentsMap.get(fileName)); + attachment.setType(FileTypeEnum.DOCUMENT_INFO); + } + }); + + // 娣诲姞椤圭洰闄勪欢鍏宠仈琛� + fileService.saveBatch(attachments); + } catch (IOException e) { + log.error(e.getMessage()); + throw new RuntimeException(e); + } finally { + deleteDirectoryOrFile(tempZip); + deleteDirectoryOrFile(tempDir); + } + } + + private static void deleteDirectoryOrFile(java.io.File file) { + if (ObjectUtil.isNull(file)) { + return; + } + + if (file.isDirectory()) { + java.io.File[] files = file.listFiles(); + if (files != null) { + for (java.io.File f : files) { + deleteDirectoryOrFile(f); + } + } + } + file.delete(); + } + /** + * 椤圭洰鍚嶇О鏍¢獙閲嶅 + * @return + */ + public void checkProjectNameUnique(ProjectInfo projectInfo) { + if (StrUtil.isBlank(projectInfo.getProjectName())) { + throw new BaseException("椤圭洰鍚嶇О涓嶈兘涓虹┖"); + } + Assert.isTrue(baseMapper.selectCount(Wrappers.<ProjectInfo>lambdaQuery().eq(ProjectInfo::getProjectName, projectInfo.getProjectName())) == 0, "椤圭洰鍚嶇О閲嶅"); + } + } diff --git a/common/src/main/java/com/ycl/common/utils/file/FileUploadUtils.java b/common/src/main/java/com/ycl/common/utils/file/FileUploadUtils.java index bab638f..586f5b5 100644 --- a/common/src/main/java/com/ycl/common/utils/file/FileUploadUtils.java +++ b/common/src/main/java/com/ycl/common/utils/file/FileUploadUtils.java @@ -2,7 +2,9 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.util.Objects; import org.apache.commons.io.FilenameUtils; import org.springframework.web.multipart.MultipartFile; @@ -85,7 +87,44 @@ throw new IOException(e.getMessage(), e); } } - + /** + * 鏂囦欢涓婁紶 + * + * @param baseDir 鐩稿搴旂敤鐨勫熀鐩綍 + * @param file 涓婁紶鐨勬枃浠� + * @return 杩斿洖涓婁紶鎴愬姛鐨勬枃浠跺悕 + * @throws FileSizeLimitExceededException 濡傛灉瓒呭嚭鏈�澶уぇ灏� + * @throws FileNameLengthLimitExceededException 鏂囦欢鍚嶅お闀� + * @throws IOException 姣斿璇诲啓鏂囦欢鍑洪敊鏃� + * @throws InvalidExtensionException 鏂囦欢鏍¢獙寮傚父 + */ + public static final String uploadIOFile(String baseDir, java.io.File file) + throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException + { + int fileNamelength = Objects.requireNonNull(file.getName()).length(); + if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) + { + throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); + } + //涓婁紶IOFile鏂囦欢閫昏緫 + String fileName = file.getName(); + //甯︽棩鏈熷墠缂�鐨勬枃浠跺悕 + String formatName = StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), + FilenameUtils.getBaseName(fileName), Seq.getId(Seq.uploadSeqType), fileName.substring(fileName.lastIndexOf(".") + 1)); + // /home/projectManagement/uploadPath/upload/2024/11/11/xxxx + String url = baseDir + File.separator + formatName; + File newFile = new File(url); + if (!newFile.exists()) + { + if (!newFile.getParentFile().exists()) + { + newFile.getParentFile().mkdirs(); + } + } + //澶嶅埗鏂囦欢鍒颁笂浼犺矾寰� + Files.copy(file.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + return getPathFileName(baseDir, formatName); + } /** * 鏂囦欢涓婁紶 * diff --git a/common/src/main/java/com/ycl/common/utils/poi/ExcelUtil.java b/common/src/main/java/com/ycl/common/utils/poi/ExcelUtil.java index 4a13764..6347658 100644 --- a/common/src/main/java/com/ycl/common/utils/poi/ExcelUtil.java +++ b/common/src/main/java/com/ycl/common/utils/poi/ExcelUtil.java @@ -24,6 +24,10 @@ import java.util.UUID; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; + +import com.alibaba.excel.EasyExcel; +import com.ycl.common.utils.excel.core.ExcelListener; +import com.ycl.common.utils.excel.core.ExcelResult; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.reflect.FieldUtils; @@ -500,6 +504,20 @@ } /** + * 浣跨敤鑷畾涔夌洃鍚櫒 寮傛瀵煎叆 鑷畾涔夎繑鍥� + * + * @param is 杈撳叆娴� + * @param clazz 瀵硅薄绫诲瀷 + * @param listener 鑷畾涔夌洃鍚櫒 + * @return 杞崲鍚庨泦鍚� + */ + public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, ExcelListener<T> listener) { + EasyExcel.read(is, clazz, listener).sheet().doRead(); + return listener.getExcelResult(); + } + + + /** * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟 * * @param list 瀵煎嚭鏁版嵁闆嗗悎 -- Gitblit v1.8.0