yangys
2025-09-29 4c7296d45efe849dc70a3b2e2240c905481a91c9
blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/MdmProgramImportService.java
@@ -1,376 +1,399 @@
package org.springblade.mdm.program.service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
import org.springblade.core.mp.base.BizEntity;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BizServiceImpl;
import org.springblade.core.oss.OssTemplate;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.FileUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.IoUtil;
import org.springblade.mdm.flow.entity.ApproveRecord;
import org.springblade.mdm.flow.service.ApproveRecordService;
import org.springblade.mdm.flow.service.CureFlowService;
import org.springblade.mdm.program.entity.NcNode;
import org.springblade.mdm.program.entity.NcProgram;
import org.springblade.mdm.basesetting.machine.service.MachineService;
import org.springblade.mdm.basesetting.machine.entity.Machine;
import org.springblade.mdm.commons.contants.ZipConstants;
import org.springblade.mdm.gkw.programnode.vo.ProgramNameVO;
import org.springblade.mdm.gkw.task.entity.MachineBackTask;
import org.springblade.mdm.gkw.task.service.MachineBackTaskService;
import org.springblade.mdm.machinefile.entity.FileSendRecord;
import org.springblade.mdm.machinefile.service.FileSendRecordService;
import org.springblade.mdm.program.entity.NcProgramExchange;
import org.springblade.mdm.program.mapper.NcProgramExchangeMapper;
import org.springblade.mdm.program.vo.DncSendBackData;
import org.springblade.mdm.program.service.programannotation.*;
import org.springblade.mdm.program.vo.MdmProgramImportVO;
import org.springblade.mdm.utils.CustomBinaryReader;
import org.springblade.mdm.utils.FileContentUtil;
import org.springblade.mdm.utils.ProgramFileNameParser;
import org.springblade.system.pojo.entity.DictBiz;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.nio.file.*;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
 * MDM程序导入(工控网功能)
 *
 * 目前工控网展现形式未定,暂时实现暂停
 * @author yangys
 */
@Slf4j
@Service
@AllArgsConstructor
public class MdmProgramImportService extends BizServiceImpl<NcProgramExchangeMapper, NcProgramExchange> {
   private final CureFlowService cureFlowService;
   private final NcProgramService ncProgramService;
   private final NcNodeService ncNodeService;
   private final ApproveRecordService approveRecordService;
   private final BladeRedis bladeRedis;
   private final OssTemplate ossTemplate;
   @Autowired
   private BladeRedis bladeRedis;
   @Autowired
   private ProgramAnnotationService programAnnotationService;
   @Autowired
   private MachineService machineService;
   @Autowired
   private FileSendRecordService fileSendRecordService;
   @Autowired
   private OssTemplate ossTemplate;
   @Autowired
   private AnnotationProcessorHelper annotationProcessorHelper;
   @Autowired
   private MachineBackTaskService machineBackTaskService;
   private String getFileKey(){
      return "mdmimpfile-"+ AuthUtil.getUserId();
      return "mdmgkwimpfile-"+ AuthUtil.getUserId();
   }
   /**
    * MDM导入文件上传
    * 工控MDM导入文件上传
    * @param file MDM涉密网导出文件
    * @return
    */
   public List<MdmProgramImportVO> mdmImportUpload(MultipartFile file) {
      List<MdmProgramImportVO> list;
      try {
         BladeFile bfile = ossTemplate.putFile(file);//上传,供后续入库使用
         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 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);
         }else{
            //普通文件,直接放入extract文件夹
            file.transferTo(Paths.get(extractDir.toString()+File.separator+file.getOriginalFilename()));
         }
         //设置一个缓存,2小时过期
         bladeRedis.setEx(getFileKey(),bfile.getName(), Duration.ofHours(2));
         //String fileName = file.getOriginalFilename();
         //InputStream zipFileInputStream = FileExchangeUtil.convertFileToZip(file.getInputStream());
         InputStream zipFileInputStream = file.getInputStream();//test
         byte[] bytes = FileUtil.copyToByteArray(zipFileInputStream);
         list = parseMdmZipFromByteArray(bytes);
         //读取文件目录
         list = readTempDir(extractDir);
      } catch (IOException e) {
         log.error("上传dnc回传文件失败",e);
         list = Collections.emptyList();
         log.error("导入涉密网摆渡文件失败",e);
         throw new ServiceException("解析DNC回传数据失败");
      }
      return list;
   }
   InputStream convertFileToZip(InputStream inputStream) throws IOException {
      File tempFile = createTempFile();
      FileOutputStream fos = new FileOutputStream(tempFile);
      CustomBinaryReader.read(inputStream,fos);
      FileInputStream dInstream = new FileInputStream(tempFile);
      return dInstream;
   }
   /**
    * 创建一个临时文件
    * @return
    * @throws IOException
    * 解压zip包到临时路径
    * @param zipFilePath zip包文件服务器上的路径
    * @param extractDir 目标目录
    * @throws IOException 文件操作异常
    */
   File createTempFile() throws IOException {
      Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"));
      // 在临时目录中创建文件
      String tfilename = "t"+System.currentTimeMillis();
      Path tempFile = Files.createTempFile(tempDir, tfilename, ".tmp");
      System.out.println("创建的临时文件: " + tempFile);
      return tempFile.toFile();
   public void extractZipToTempDir(Path zipFilePath,Path extractDir) throws IOException{
      for (String encoding : ZipConstants.TRY_ENCODINGS) {
         try {
            extractZipToTempDirWithCharset(zipFilePath,extractDir,Charset.forName(encoding));
            log.error("使用编码 {} 解析成功 ",encoding);
            break;
         } catch (Exception e) {
            log.error("使用编码 {} 解析失败: ",encoding,e);
         }
      }
   }
   public static List<MdmProgramImportVO> parseMdmZipFromByteArray(byte[] zipData) throws IOException {
      List<MdmProgramImportVO> list = new ArrayList<>();
      Map<String,String> fileMd5Map = new HashMap<>();
      Map<String,MdmProgramImportVO> fileDataMap = new HashMap<>();
      try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(zipData);
          ZipFile zipFile = new ZipFile(channel)) {
   public void extractZipToTempDirWithCharset(Path zipFilePath, Path extractDir, Charset charset) throws IOException {
      // 获取系统临时目录
      String tempDir = System.getProperty("java.io.tmpdir");
         ZipArchiveEntry entry;
         Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
         while (entries.hasMoreElements()) {
            entry = entries.nextElement();
      // 创建解压目标目录(在临时目录下创建一个唯一子目录)
      try (InputStream fis = Files.newInputStream(zipFilePath);
          ZipInputStream zis = new ZipInputStream(fis,charset)) {
            String entryName = entry.getName();
         ZipEntry zipEntry = zis.getNextEntry();
         while (zipEntry != null) {
            Path newPath = zipSlipProtect(zipEntry, extractDir);
            if (!entry.isDirectory()) {
               //直接解析程序的json文件
               if(entryName.equals(NcProgramExportDNCService.PROGRAM_JSON_FILE)){
                  try (InputStream inputStream = zipFile.getInputStream(entry)) {
                     String jsonStr = IoUtil.readToString(inputStream);
                     JSONArray jsonArray = JSONArray.parseArray(jsonStr);
                     for(int i=0;i<jsonArray.size();i++){
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        MdmProgramImportVO d = new MdmProgramImportVO();
                        d.setName(jsonObject.getString("name"));
                        d.setId(jsonObject.getLong("id"));
                        d.setCode(jsonObject.getString("code"));
                        d.setDescription(jsonObject.getString("description"));
                        d.setCategory(jsonObject.getString("category"));
                        d.setBindNcNodeId(jsonObject.getLong("bindNcNodeId"));
                        d.setIsLastEdition(jsonObject.getInteger("isLastEdition"));
                        d.setIsLocked(jsonObject.getInteger("isLocked"));
                        d.setIsTest(jsonObject.getInteger("isTest"));
                        d.setMachineCode(jsonObject.getString("machineCode"));
                        d.setNcNodeId(jsonObject.getLong("ncNodeId"));
                        d.setPartNo(jsonObject.getString("partNo"));
                        d.setProcessEdition(jsonObject.getString("processEdition"));
                        fileDataMap.put(d.getName(),d);
                        list.add(d);
                     }
                  }
               }else{
                  try (InputStream inputStream = zipFile.getInputStream(entry)) {
                     fileMd5Map.put(entryName,DigestUtils.md5Hex(inputStream));//获取文件MD5
                  }
            if (zipEntry.isDirectory()) {
               Files.createDirectories(newPath);
            } else {
               // 确保父目录存在
               if (newPath.getParent() != null) {
                  Files.createDirectories(newPath.getParent());
               }
               // 写入文件
               try (OutputStream fos = Files.newOutputStream(newPath)) {
                  byte[] buffer = new byte[1024];
                  int len;
                  while ((len = zis.read(buffer)) > 0) {
                     fos.write(buffer, 0, len);
                  }
               }
            }
            zipEntry = zis.getNextEntry();
         }
         zis.closeEntry();
      }
      //设置md5值
      fileDataMap.forEach((k,v)->{
         if(fileMd5Map.containsKey(k)){
            v.setMd5(fileMd5Map.get(k));
         }
      });
      return list;
   }
   /**
    * 防止ZIP Slip攻击
    * @param zipEntry zip内部文件路径
    * @param targetDir 目标文件夹
    * @return 文件路径
    * @throws IOException 操作文件IO异常
    */
   Path zipSlipProtect(ZipEntry zipEntry, Path targetDir) throws IOException {
      Path targetDirResolved = targetDir.resolve(zipEntry.getName());
      // 规范化路径
      Path normalizePath = targetDirResolved.normalize();
      if (!normalizePath.startsWith(targetDir)) {
         throw new IOException("恶意ZIP条目: " + zipEntry.getName());
      }
      return normalizePath;
   }
   /**
    * 读取解压文件夹下所有文件 解析成vo列表
    * @param extractDir 解压文件夹
    * @return vo列表
    * @throws IOException 解析文件的异常
    */
   public List<MdmProgramImportVO> readTempDir(Path extractDir) throws IOException {
      List<MdmProgramImportVO> list = new ArrayList<>();
      try (Stream<Path> paths = Files.walk(extractDir)) {
         List<Path> filePathList = paths
            .filter(Files::isRegularFile).toList();  // 只保留普通文件,排除目录
         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) {
                     if (Files.isRegularFile(subPath)) {
                        System.out.println("找到文件: " + subPath);
                     }
                  }
               }
            } else if (Files.isRegularFile(path)) {
               System.out.println("找到文件2: " + path);
               //这里 找到的文件不是
               list.add(readFileToVO(path));
            }
         }
      }*/
      return list;
   }
   public static byte[] getUTF8BytesFromGBKString(String gbkStr) {
      int n = gbkStr.length();
      byte[] utfBytes = new byte[3 * n];
      int k = 0;
      for (int i = 0; i < n; i++) {
         int m = gbkStr.charAt(i);
         if (m < 128 && m >= 0) {
            utfBytes[k++] = (byte) m;
            continue;
         }
         utfBytes[k++] = (byte) (0xe0 | (m >> 12));
         utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
         utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
      }
      if (k < utfBytes.length) {
         byte[] tmp = new byte[k];
         System.arraycopy(utfBytes, 0, tmp, 0, k);
         return tmp;
      }
      return utfBytes;
   }
   ProgramNameVO tryParseProgramName(String fiilename){
      ProgramNameVO pnmameVO = ProgramFileNameParser.parseProgramName(fiilename);//标准utf8编码
      if(pnmameVO.getDrawingNo() == null) {
         //使用GBK编码解析
         pnmameVO = ProgramFileNameParser.parseProgramName(new String(getUTF8BytesFromGBKString(fiilename), StandardCharsets.UTF_8));
      }
      return pnmameVO;
   }
   /**
    * 将文件组织成VO
    * @param path 文件path
    * @return vo
    */
   MdmProgramImportVO readFileToVO(Path path) throws UnsupportedEncodingException {
      MdmProgramImportVO vo = new MdmProgramImportVO();
      vo.setFilename(path.getFileName().toString());
      ProgramNameVO progNmameVO = tryParseProgramName(vo.getFilename());
      vo.setDrawingNo(progNmameVO.getDrawingNo());
      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.reset();
         String statusLine = FileContentUtil.readLineAt(bas,defAnnoProperties.getStatusLineIndex());
         log.info("sendPathLine={}", sendPathLine);
         Machine matchedMachine = machineService.getMachineBySendPathAnnotation(sendPathLine);
         if (matchedMachine != null) {
            vo.setName(progNmameVO.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;
   }
   /**
    * 入库mdm涉密网文件
    * @param ids id列表逗号分隔
    * @return
    */
   public void mdmFileAccept(String ids) throws IOException {
      String pkgFileName = bladeRedis.get(getFileKey());
      List<FileSendRecord>  importedRecords = new ArrayList<>();
      List<String> idList = Func.toStrList(ids);
      List<Long> idList = Func.toLongList(ids);
      //
      updateProgramFile(pkgFileName,idList);
      String dictStr = bladeRedis.get(getFileKey());
      if(dictStr == null){
         throw new ServiceException("文件缓存已过期,请重新上传文件。");
      }
      Path extractDir = Paths.get(dictStr);
      List<MdmProgramImportVO> list = readTempDir(extractDir);
      List<NcProgram> progList = ncProgramService.listByIds(idList);
      NcProgramExchange exchange;
      //List<DictBiz> annoDictList = programAnnotationService.getAnnotionDictList();
      String destFileFull;
      for(String str : idList){
         Optional<MdmProgramImportVO> optVO = list.stream().filter(vo -> vo.getId().equals(str)).findFirst();
      for(NcProgram prog:progList){
         exchange = new NcProgramExchange();
         exchange.setName(prog.getName());
         exchange.setExchangeType(2);//回传
         exchange.setNcProgramId(prog.getId());
         if(optVO.isEmpty()){
            continue;
         }
         MdmProgramImportVO vo = optVO.get();
         this.save(exchange);
         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());
         }
         try(InputStream inputStream = ossTemplate.statFileStream(record.getOssName())){
            //读取程序状态
            Machine machine = this.machineService.getByCode(record.getMachineCode());
            AnnotationProcessor processor = annotationProcessorHelper.getProcessor(machine.getControlSystem());
            AnnotationData annotationData = processor.readAnnotationData(inputStream);
            record.setDeviation(annotationData.getDeviation());
            ProgramNameVO nameVO = ProgramFileNameParser.parseProgramName(record.getName());
            record.setDeviationSerial(nameVO.lgSerial());
            record.setProgramStatus(annotationData.getProgramStatus());
         }
         fileSendRecordService.save(record);
         importedRecords.add(record);
      }
      machineBackTaskService.saveBatch(parseMachineBackTask(importedRecords));
   }
   /**
    * 更新程序文件
    * @param pkgFileName mdm程序包
    * @param idList 选定入库的
    * 创建机床回传任务
    * @param importedRecords 导入记录列表
    */
   private void updateProgramFile(String pkgFileName,List<Long> idList) throws IOException {
      InputStream inputStream = this.ossTemplate.statFileStream(pkgFileName);
      byte[] bytes = FileUtil.copyToByteArray(inputStream);
   List<MachineBackTask> parseMachineBackTask(List<FileSendRecord>  importedRecords){
      List<FileSendRecord> recList = importedRecords.stream().filter(r -> AnnotationUtil.SQ.equals(r.getProgramStatus())
         || AnnotationUtil.LG.equals(r.getProgramStatus())).toList();
      List<NcNode> nodeList = new ArrayList<>();
      List<NcProgram> progList = new ArrayList<>();
      List<ApproveRecord> recordList = new ArrayList<>();
      Map<String,FileSendRecord> map = new HashMap<>();
      for(FileSendRecord record : recList){
         ProgramNameVO nameVO = ProgramFileNameParser.parseProgramName(record.getName());
         String key = record.getMachineCode()+","+nameVO.logicProgramName();
      try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(bytes);
          ZipFile zipFile = new ZipFile(channel)) {
         ZipArchiveEntry entry;
         Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
         while (entries.hasMoreElements()) {
            entry = entries.nextElement();
            String entryName = entry.getName();
            if (!entry.isDirectory()) {
               if(entryName.equals(NcProgramExportDNCService.PROGRAM_JSON_FILE)){
                  try (InputStream insJson = zipFile.getInputStream(entry)) {
                     String jsonStr = IoUtil.readToString(insJson);
                     JSONArray jsonArray = JSONArray.parseArray(jsonStr);
                     for(int i=0;i<jsonArray.size();i++){
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        NcProgram d = new NcProgram();
                        d.setId(jsonObject.getLong("id"));
                        d.setName(jsonObject.getString("name"));
                        d.setCode(jsonObject.getString("code"));
                        d.setDescription(jsonObject.getString("description"));
                        d.setCategory(jsonObject.getString("category"));
                        d.setBindNcNodeId(jsonObject.getLong("bindNcNodeId"));
                        d.setIsLastEdition(jsonObject.getInteger("isLastEdition"));
                        d.setIsLocked(jsonObject.getInteger("isLocked"));
                        d.setIsTest(jsonObject.getInteger("isTest"));
                        d.setMachineCode(jsonObject.getString("machineCode"));
                        d.setNcNodeId(jsonObject.getLong("ncNodeId"));
                        d.setPartNo(jsonObject.getString("partNo"));
                        d.setProcessEdition(jsonObject.getString("processEdition"));
                        setBaseProperties(d,jsonObject);
                        progList.add(d);
                     }
                  }
               }else if(entryName.equals(NcProgramExportDNCService.NODE_JSON_FILE)){
                  try (InputStream insJson = zipFile.getInputStream(entry)) {
                     String jsonStr = IoUtil.readToString(insJson);
                     JSONArray jsonArray = JSONArray.parseArray(jsonStr);
                     for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        NcNode node = new NcNode();
                        node.setId(jsonObject.getLong("id"));
                        node.setName(jsonObject.getString("name"));
                        node.setDescription(jsonObject.getString("description"));
                        node.setNodeType(jsonObject.getString("nodeType"));
                        node.setProcessName(jsonObject.getString("processName"));
                        node.setPartNo(jsonObject.getString("partNo"));
                        node.setMachineCode(jsonObject.getString("machineCode"));
                        node.setParentId(jsonObject.getLong("parentId"));
                        node.setParentIds(jsonObject.getString("parentIds"));
                        node.setIsCured(jsonObject.getInteger("isCured"));
                        setBaseProperties(node,jsonObject);
                        nodeList.add(node);
                     }
                  }
               }else if(entryName.equals(NcProgramExportDNCService.APPROVE_RECORD_JSON_FILE)){
                  try (InputStream insJson = zipFile.getInputStream(entry)) {
                     String jsonStr = IoUtil.readToString(insJson);
                     JSONArray jsonArray = JSONArray.parseArray(jsonStr);
                     for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        ApproveRecord record = new ApproveRecord();
                        record.setId(jsonObject.getLong("id"));
                        record.setNcProgramId(jsonObject.getLong("ncProgramId"));
                        record.setUserId(jsonObject.getLong("userId"));
                        record.setUserNickname(jsonObject.getString("userNickname"));
                        record.setOperateResult(jsonObject.getString("operateResult"));
                        record.setOperateTime(jsonObject.getDate("operateTime"));
                        setBaseProperties(record,jsonObject);
                        recordList.add(record);
                     }
                  }
               }
            }
         }
         map.put(key,record);
      }
      List<MachineBackTask> backTasks = new ArrayList<>();
      for(String key : map.keySet()){
         MachineBackTask task = new MachineBackTask();
         task.setTaskType(MachineBackTask.TASK_TYPE_PROGRAM);
      try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(bytes);
          ZipFile zipFile = new ZipFile(channel)) {
         FileSendRecord record = map.get(key);
         task.setMachineCode(record.getMachineCode());
         ZipArchiveEntry entry;
         Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
         while (entries.hasMoreElements()) {
            entry = entries.nextElement();
         ProgramNameVO nameVO = ProgramFileNameParser.parseProgramName(record.getName());
         task.setDeviation(record.getDeviation());
         task.setDeviationSerial(record.getDeviationSerial());
            String entryName = entry.getName();
            if (!entry.isDirectory() && !entryName.equals(NcProgramExportDNCService.PROGRAM_JSON_FILE)) {
               for(NcProgram prog:progList){
                  if(prog.getName().equals(entryName)){
                     try (InputStream ncFileStream = zipFile.getInputStream(entry)) {
                        BladeFile bfile = this.ossTemplate.putFile(prog.getName(),ncFileStream);
                        prog.setOssName(bfile.getName());
                        prog.setUrl(bfile.getLink());
                     }
                     break;
                  }
               }
            }
         }
         task.setProgramName(nameVO.logicProgramName());
         task.setSegCount(nameVO.getSegmentCount());
         backTasks.add(task);
      }
      for(NcNode node:nodeList){
         NcNode nodeTemp = this.ncNodeService.getById(node.getId());
         if(nodeTemp == null){
            ncNodeService.save(node);
         }else{
            ncNodeService.updateById(node);
         }
      }
      for(NcProgram prog:progList){
         NcProgram ncTemp = ncProgramService.getById(prog.getId());
         if(ncTemp == null){
            ncProgramService.save(prog);
         }else{
            ncProgramService.updateById(prog);
         }
      }
      for(ApproveRecord record:recordList) {
         ApproveRecord recordTemp = this.approveRecordService.getById(record.getId());
         if (recordTemp == null) {
            approveRecordService.save(record);
         } else {
            approveRecordService.updateById(record);
         }
      }
   }
   void setBaseProperties(BizEntity entity,JSONObject jsonObject){
      entity.setCreateTime(jsonObject.getDate("createTime"));
      entity.setUpdateTime(jsonObject.getDate("updateTime"));
      entity.setStatus(jsonObject.getInteger("status"));
      entity.setCreateUser(jsonObject.getLong("createUser"));
      entity.setUpdateUser(jsonObject.getLong("updateUser"));
      //提取程序包名,机床编码集合
      return backTasks;
   }
}