yangys
2025-09-22 c0ccbb980be6975389f09ad13dcabd7d3156dae3
blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/MdmProgramImportService.java
@@ -4,6 +4,7 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BizServiceImpl;
@@ -14,6 +15,8 @@
import org.springblade.core.tool.utils.Func;
import org.springblade.mdm.basesetting.machine.service.MachineService;
import org.springblade.mdm.basesetting.machine.entity.Machine;
import org.springblade.mdm.commons.contants.RegExpConstants;
import org.springblade.mdm.gkw.programnode.vo.ProgramNameVO;
import org.springblade.mdm.machinefile.entity.FileSendRecord;
import org.springblade.mdm.machinefile.service.FileSendRecordService;
import org.springblade.mdm.program.entity.NcProgramExchange;
@@ -21,6 +24,7 @@
import org.springblade.mdm.program.service.programannotation.AnnotationProperties;
import org.springblade.mdm.program.vo.MdmProgramImportVO;
import org.springblade.mdm.utils.FileContentUtil;
import org.springblade.mdm.utils.ProgramFileNameParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@@ -32,6 +36,8 @@
import java.time.Duration;
import java.util.*;
import java.nio.file.*;
import java.util.regex.Matcher;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
@@ -61,29 +67,34 @@
    * @return
    */
   public List<MdmProgramImportVO> mdmImportUpload(MultipartFile file) {
      List<MdmProgramImportVO> list = new ArrayList<>();
      List<MdmProgramImportVO> list;
      try {
         if(file == null || file.isEmpty()){
            throw new ServiceException("文件为空");
         }
         /*
         if(!StringUtils.endsWith(file.getOriginalFilename(),".zip")){
            throw new ServiceException("文件必须为zip包");
         }
         }*/
         String tempDir = System.getProperty("java.io.tmpdir");
         Path tempPath = Paths.get(tempDir);
         // 创建解压目标目录(在临时目录下创建一个唯一子目录)
         Path tempZipFile = Files.createTempFile("mdmimpfile-"+System.currentTimeMillis(), ".zip");
         file.transferTo(tempZipFile);
         // 创建解压目标目录(在临时目录下创建一个唯一子目录)
         Path extractDir = Files.createTempDirectory(tempPath, "unzip_");
         Path extractDir = Files.createTempDirectory(tempPath, "unzip_"+System.currentTimeMillis());
         bladeRedis.setEx(getFileKey(),extractDir.toString(), Duration.ofHours(2));
         if(StringUtils.endsWithIgnoreCase(file.getOriginalFilename(),".zip")){
            // 创建解压目标目录(在临时目录下创建一个唯一子目录)
            Path tempZipFile = Files.createTempFile("mdmimpfile-"+System.currentTimeMillis(), ".zip");
            file.transferTo(tempZipFile);
            extractZipToTempDir(tempZipFile,extractDir);
         extractZipToTempDir(tempZipFile,extractDir);
         }else{
            //普通文件,直接放入extract文件夹
            String basename = FilenameUtils.getBaseName(file.getOriginalFilename());
            String ext = FilenameUtils.getExtension(file.getOriginalFilename());
            //Path filepath = Files.createTempFile(extractDir,basename,StringUtils.isEmpty(ext) ? "": "."+ext);
            //Path filepath = Files.createFile();
            file.transferTo(Paths.get(extractDir.toString()+File.separator+file.getOriginalFilename()));
         }
         //读取文件目录
         list = readTempDir(extractDir);
@@ -94,10 +105,15 @@
      return list;
   }
   /**
    * 解压zip包到临时路径
    * @param zipFilePath zip包文件服务器上的路径
    * @param extractDir 目标目录
    * @throws IOException 文件操作异常
    */
   public void extractZipToTempDir(Path zipFilePath,Path extractDir) throws IOException {
      // 获取系统临时目录
      String tempDir = System.getProperty("java.io.tmpdir");
      Path tempPath = Paths.get(tempDir);
      // 创建解压目标目录(在临时目录下创建一个唯一子目录)
      try (InputStream fis = Files.newInputStream(zipFilePath);
@@ -132,10 +148,10 @@
   /**
    * 防止ZIP Slip攻击
    * @param zipEntry
    * @param targetDir
    * @return
    * @throws IOException
    * @param zipEntry zip内部文件路径
    * @param targetDir 目标文件夹
    * @return 文件路径
    * @throws IOException 操作文件IO异常
    */
   Path zipSlipProtect(ZipEntry zipEntry, Path targetDir) throws IOException {
      Path targetDirResolved = targetDir.resolve(zipEntry.getName());
@@ -150,16 +166,28 @@
      return normalizePath;
   }
   /**
    * 读取解压文件夹下所有文件 解析成vo列表
    * @param extractDir 解压文件夹
    * @return vo列表
    * @throws IOException 解析文件的异常
    */
   public List<MdmProgramImportVO> readTempDir(Path extractDir) throws IOException {
      List<MdmProgramImportVO> list = new ArrayList<>();
      //List<Machine> machines = machineService.getEnableMachines();
      try (Stream<Path> paths = Files.walk(extractDir)) {
         List<Path> filePathList = paths
            .filter(Files::isRegularFile).toList();  // 只保留普通文件,排除目录
            //.collect(Collectors.toList());
         //System.out.println("所有文件"+filePathList);
         for(Path path : filePathList){
            list.add(readFileToVO(path));
         }
      }
      /*
      //读取所有文件夹
      try (DirectoryStream<Path> stream = Files.newDirectoryStream(extractDir)) {
         for (Path path : stream) {
            if (Files.isDirectory(path)) {
               // 如果是子目录,读取其中的文件
               try (DirectoryStream<Path> subStream = Files.newDirectoryStream(path)) {
                  for (Path subPath : subStream) {
@@ -171,70 +199,73 @@
            } else if (Files.isRegularFile(path)) {
               System.out.println("找到文件2: " + path);
               //这里 找到的文件不是
               MdmProgramImportVO vo = new MdmProgramImportVO();
               vo.setFilename(path.getFileName().toString());
               vo.setDrawingNo(parseDrawingNo(vo.getFilename()));
               try (InputStream inputStream = Files.newInputStream(path)) {
                  // 使用输入流读取文件内容
                  byte[] buffer = new byte[2000];
                  inputStream.read(buffer);
                  vo.setMd5(DigestUtils.md5Hex(buffer));
               } catch (IOException e) {
                  log.error("读取文件md5失败",e);
               }
               try (InputStream inputStream = Files.newInputStream(path, StandardOpenOption.READ)) {
                  // 使用输入流读取文件内容
                  ByteArrayInputStream bas = new ByteArrayInputStream(inputStream.readAllBytes());
                  AnnotationProperties defAnnoProperties = AnnotationProperties.getDefault();
                  String sendPathLine = FileContentUtil.readLineAt(bas,defAnnoProperties.getSendPathLineIndex());
                  //bas.mark(0);
                  bas.reset();
                  String statusLine = FileContentUtil.readLineAt(bas,defAnnoProperties.getStatusLineIndex());
                  log.info("sendPathLine={}", sendPathLine);
                  Machine matchedMachine = machineService.getMachineBySendPathAnnotation(sendPathLine);
                  /*
                  for (Machine machine : machines) {
                     if(Func.isNotBlank(machine.getProgSendDir()) && sendPathLine.contains(machine.getProgSendDir())){
                        matchedMachine = machine;
                        break;
                     }
                  }
                   */
                  if (matchedMachine != null) {
                     vo.setName(parseProgramName(vo.getFilename()));
                     vo.setMachineCode(matchedMachine.getCode());
                     vo.setFullPath(path.toString());//文件地址
                     vo.setSendPath(matchedMachine.getProgSendDir());
                     vo.setId(vo.getFullPath());
                     vo.setProgramStatus(programAnnotationService.removeAnnotation(matchedMachine.getControlSystem(),statusLine));
                     list.add(vo);
                  }
               } catch (IOException e) {
                  log.error("读取文件md5失败",e);
               }
               list.add(readFileToVO(path));
            }
         }
      }
      }*/
      return list;
   }
   /**
    * 将文件组织成VO
    * @param path 文件path
    * @return vo
    */
   MdmProgramImportVO readFileToVO(Path path){
      MdmProgramImportVO vo = new MdmProgramImportVO();
      vo.setFilename(path.getFileName().toString());
      ProgramNameVO pnmameVO = ProgramFileNameParser.parseProgramName(vo.getFilename());
      vo.setDrawingNo(pnmameVO.getDrawingNo());
      //vo.setDrawingNo(parseDrawingNo(vo.getFilename()));
      try (InputStream inputStream = Files.newInputStream(path)) {
         // 使用输入流读取文件内容
         byte[] buffer = new byte[2000];
         inputStream.read(buffer);
         vo.setMd5(DigestUtils.md5Hex(buffer));
      } catch (IOException e) {
         log.error("读取文件md5失败",e);
      }
      try (InputStream inputStream = Files.newInputStream(path, StandardOpenOption.READ)) {
         // 使用输入流读取文件内容
         ByteArrayInputStream bas = new ByteArrayInputStream(inputStream.readAllBytes());
         AnnotationProperties defAnnoProperties = AnnotationProperties.getDefault();
         String sendPathLine = FileContentUtil.readLineAt(bas,defAnnoProperties.getSendPathLineIndex());
         //bas.mark(0);
         bas.reset();
         String statusLine = FileContentUtil.readLineAt(bas,defAnnoProperties.getStatusLineIndex());
         log.info("sendPathLine={}", sendPathLine);
         Machine matchedMachine = machineService.getMachineBySendPathAnnotation(sendPathLine);
         if (matchedMachine != null) {
            //vo.setName(parseProgramName(vo.getFilename()));
            vo.setName(pnmameVO.logicProgramName());
            vo.setMachineCode(matchedMachine.getCode());
            vo.setFullPath(path.toString());//文件地址
            vo.setSendPath(matchedMachine.getProgSendDir());
            vo.setId(vo.getFullPath());
            vo.setProgramStatus(programAnnotationService.removeAnnotation(matchedMachine.getControlSystem(),statusLine));
         }
      } catch (IOException e) {
         log.error("读取文件失败",e);
         throw new ServiceException("导入程序失败"+path.getFileName().toString()+","+e.getMessage());
      }
      return vo;
   }
   /**
    * 解析出零组件好
    * @param filename
    * @return
    */
   /*
   String parseDrawingNo(String filename){
      /*
      String drawingNo = "";
      int idx = filename.lastIndexOf("-");
      String temp;
@@ -262,6 +293,8 @@
      }
      return drawingNo;
   }
   String parseProgramName(String filename){
@@ -282,12 +315,10 @@
            }
         }
         //以上去掉了最后2段段数和段号
      }
      return programName;
   }
*/
   /**
    * 入库mdm涉密网文件
    * @param ids id列表逗号分隔
@@ -298,35 +329,37 @@
      String dictStr = bladeRedis.get(getFileKey());
      if(dictStr == null){
         throw new ServiceException("");
         throw new ServiceException("文件缓存已过期,请重新上传文件。");
      }
      Path extractDir = Paths.get(dictStr);
      List<MdmProgramImportVO> list = readTempDir(extractDir);
      String destFileFull;
      for(String str : idList){
         for(MdmProgramImportVO vo : list){
            if(StringUtils.equals(vo.getFullPath(),str)){
               destFileFull = vo.getSendPath()+File.separator+vo.getFilename();
               File destFile = new File(destFileFull);
               FileUtils.forceMkdirParent(destFile);
               FileUtils.copyFile(new File(str),destFile);
         Optional<MdmProgramImportVO> optVO = list.stream().filter(vo -> vo.getId().equals(str)).findFirst();
               FileSendRecord record = new FileSendRecord();
               record.setName(destFile.getName());
               Path destPath = Paths.get(destFileFull);
               record.setMachineCode(vo.getMachineCode());
               record.setFileSize(Files.size(destPath));
               try(InputStream inputStream = new FileInputStream(destFile)){
                  BladeFile bFile = ossTemplate.putFile(record.getName(), inputStream);
                  record.setOssName(bFile.getName());
               }
               fileSendRecordService.save(record);
               break;
            }
         if(optVO.isEmpty()){
            continue;
         }
         MdmProgramImportVO vo = optVO.get();
         destFileFull = vo.getSendPath()+File.separator+vo.getFilename();
         File destFile = new File(destFileFull);
         FileUtils.forceMkdirParent(destFile);
         FileUtils.copyFile(new File(str),destFile);
         FileSendRecord record = new FileSendRecord();
         record.setName(destFile.getName());
         Path destPath = Paths.get(destFileFull);
         record.setMachineCode(vo.getMachineCode());
         record.setFileSize(Files.size(destPath));
         try(InputStream inputStream = new FileInputStream(destFile)){
            BladeFile bFile = ossTemplate.putFile(record.getName(), inputStream);
            record.setOssName(bFile.getName());
         }
         fileSendRecordService.save(record);
      }
   }