yangys
2025-07-08 ffd5abc74eea1f6ee6433ac11e401aaa57bcc4ab
blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExchangeService.java
@@ -1,31 +1,43 @@
package org.springblade.mdm.program.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.springblade.core.mp.base.BizServiceImpl;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
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.mdm.basesetting.machine.vo.MachineVO;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.IoUtil;
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.program.entity.NcProgramExchange;
import org.springblade.mdm.program.mapper.NcProgramExchangeMapper;
import org.springblade.mdm.program.vo.DncSendBackData;
import org.springblade.mdm.utils.CustomBinaryReader;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.io.*;
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.*;
/**
 * 下发/回传程序统计
 * 程序交换(dnc导入/导出)
 *
 * @author yangys
 */
@@ -33,118 +45,285 @@
@Service
@AllArgsConstructor
public class NcProgramExchangeService extends BizServiceImpl<NcProgramExchangeMapper, NcProgramExchange> {
   private final CureFlowService cureFlowService;
   private final NcProgramService ncProgramService;
   private final NcNodeService ncNodeService;
   private final OssTemplate ossTemplate;
   private final BladeRedis bladeRedis;
   private String getFileKey(){
      return "dncexpfile-"+ AuthUtil.getUserId();
   }
   /**
    * dnc回传文件上传
    * @param file
    * dnc回传文件上传(解析后保存入upload表)
    * @param file DNC回传文件
    * @return
    */
   public void dncSendBackUpload(MultipartFile file) {
      List<DncSendBackData> list=new ArrayList<>();
   public List<DncSendBackData> dncSendBackUpload(MultipartFile file) {
      List<DncSendBackData> list;
      try {
         String fileName = file.getOriginalFilename();
         InputStream fileInputStream = file.getInputStream();
         BladeFile bfile = ossTemplate.putFile(file);//上传,供后续入库使用
         //设置一个缓存,2小时过期
         bladeRedis.setEx(getFileKey(),bfile.getName(), Duration.ofHours(2));
         byte[] bytes = FileUtil.copyToByteArray(fileInputStream);
         //InputStream zipFileInputStream = FileExchangeUtil.convertFileToZip(file.getInputStream());
         InputStream zipFileInputStream = file.getInputStream();//test
         byte[] bytes = FileUtil.copyToByteArray(zipFileInputStream);
         list = parseDncZipFromByteArray(bytes);
         for(DncSendBackData dncSendBackData:list){
            NcProgramExchange exchange=new NcProgramExchange();
            exchange.setName(dncSendBackData.getProgramName());
            exchange.setStatus(1);//已导入
            this.save(exchange);
         }
      } catch (IOException e) {
         log.error("上传dnc文件失败",e);
         log.error("上传dnc回传文件失败",e);
         list = Collections.emptyList();
      }
      return list;
   }
   public static List<DncSendBackData> parseDncZipFromByteArray(byte[] zipData) throws IOException {
      //List<DncSendBackData> datas = new ArrayList<>();
      List<DncSendBackData> datas  = ZipFileDirectoryScanner.getFilesInDirectoryRecursive(zipData, "");
   InputStream convertFileToZip(InputStream inputStream) throws IOException {
      File tempFile = createTempFile();
      FileOutputStream fos = new FileOutputStream(tempFile);
      CustomBinaryReader.read(inputStream,fos);
      FileInputStream dInstream = new FileInputStream(tempFile);
      /*
      try (ByteArrayInputStream bis = new ByteArrayInputStream(zipData);
          ZipArchiveInputStream zis = new ZipArchiveInputStream(bis)) {
         ZipArchiveEntry entry;
         while ((entry = zis.getNextZipEntry()) != null) {
            DncSendBackData prog = new DncSendBackData();
            prog.setProgramName(entry.getName());
            if (!entry.isDirectory()) {
               System.out.println("文件名: " + entry.getName());
               System.out.println("大小: " + entry.getSize());
               // 读取文件内容到字节数组
               ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
               IOUtils.copy(zis, outputStream);
               byte[] fileContent = outputStream.toByteArray();
               // 处理文件内容...
               System.out.println("内容长度: " + fileContent.length);
            }else{
               //文件夹,读内部文件,获取文件列表
               System.out.println("文件夹程序:"+entry.getName());
               List<String> children = new ArrayList<>();
               prog.setChildren(children);
            }
            datas.add(prog);
         }
      }*/
      return datas;
      return dInstream;
   }
   /**
    * 程序下发统计分页查询
    * @param query 查询参数
    * 创建一个临时文件
    * @return
    * @throws IOException
    */
   public IPage<DncSendBackData> dncSendBackPageQuery(Query query) {
      IPage<DncSendBackData> page = this.getBaseMapper().dncSendBackpageQuery(Condition.getPage(query),query);
      return page;
   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();
   }
}
class ZipFileDirectoryScanner {
   public static List<DncSendBackData> getFilesInDirectoryRecursive(byte[] zipData, String dirPath) throws IOException {
   public static List<DncSendBackData> parseDncZipFromByteArray(byte[] zipData) throws IOException {
      List<DncSendBackData> list = new ArrayList<>();
      //List<DncSendBackData> datas  = ZipFileDirectoryScanner.getFilesInDirectoryRecursive(zipData, "");
      if (!dirPath.endsWith("/")) {
         dirPath += "/";
      }
      Map<String,String> fileMd5Map = new HashMap<>();
      Map<String,DncSendBackData> fileDataMap = new HashMap<>();
      try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(zipData);
          ZipFile zipFile = new ZipFile(channel)) {
         ZipArchiveEntry entry;
         Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
         while (entries.hasMoreElements()) {
            ZipArchiveEntry entry = entries.nextElement();
         //while ((entry = zis.getNextZipEntry()) != null) {
            entry = entries.nextElement();
            DncSendBackData prog = new DncSendBackData();
            String entryName = entry.getName();
            DncSendBackData d = new DncSendBackData();
            d.setProgramName(entryName);
            if(entry.isDirectory()){
               d.setHasChildren(true);
            }
            list.add(d);
            //if (entryName.startsWith(dirPath) && !entry.isDirectory()) {
            //   fileList.add(entryName);
            //}
            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);
                        DncSendBackData d = new DncSendBackData();
                        d.setProgramName(jsonObject.getString("name"));
                        d.setId(jsonObject.getLong("id"));
                        d.setProgramNo(jsonObject.getString("code"));
                        d.setFileBackTime(LocalDateTime.now());//到达时间
                        fileDataMap.put(d.getProgramName(),d);
                        list.add(d);
                     }
                  }
               }else{
                  try (InputStream inputStream = zipFile.getInputStream(entry)) {
                     fileMd5Map.put(entryName,DigestUtils.md5Hex(inputStream));//获取文件MD5
                  }
               }
            }
         }
      }
      //设置md5值
      fileDataMap.forEach((k,v)->{
         if(fileMd5Map.containsKey(k)){
            v.setMd5(fileMd5Map.get(k));
         }
      });
      return list;
   }
   /**
    * 入库回传文件,并启动固化流程
    * @param ids id列表逗号分隔
    * @return
    */
   public void dncFileAccept(String ids) throws IOException {
      List<Long> idList = Func.toLongList(ids);
      //
      NcProgramExchange exchange;
      String pkgFileName = bladeRedis.get(getFileKey());
      updateProgramData(pkgFileName,idList);
      List<NcProgram> progList = ncProgramService.listByIds(idList);
      for(NcProgram prog:progList){
         exchange = new NcProgramExchange();
         exchange.setName(prog.getName());
         exchange.setExchangeType(2);//回传
         exchange.setNcProgramId(prog.getId());
         this.save(exchange);
      }
      cureFlowService.startCure(progList);
   }
   void updateProgramData(String pkgFileName,List<Long> idList) throws IOException {
      InputStream inputStream = this.ossTemplate.statFileStream(pkgFileName);
      byte[] bytes = FileUtil.copyToByteArray(inputStream);
      List<NcNode> nodeList = new ArrayList<>();
      List<NcProgram> progList = new ArrayList<>();
      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()) {
               continue;
            }
            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 program = new NcProgram();
                     program.setId(jsonObject.getLong("id"));
                     if(!idList.contains(program.getId())){//不是选定入库的
                        continue;
                     }
                     program.setName(jsonObject.getString("name"));
                     program.setCode(jsonObject.getString("code"));
                     program.setDescription(jsonObject.getString("description"));
                     program.setCategory(jsonObject.getString("category"));
                     program.setBindNcNodeId(jsonObject.getLong("bindNcNodeId"));
                     program.setIsLastEdition(jsonObject.getInteger("isLastEdition"));
                     program.setIsLocked(jsonObject.getInteger("isLocked"));
                     program.setIsTest(jsonObject.getInteger("isTest"));
                     program.setMachineCode(jsonObject.getString("machineCode"));
                     program.setNcNodeId(jsonObject.getLong("ncNodeId"));
                     program.setDrawingNo(jsonObject.getString("drawingNo"));
                     program.setProcessEdition(jsonObject.getString("processEdition"));
                     setBaseProperties(program,jsonObject);
                     progList.add(program);
                  }
               }
            }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.setDrawingNo(jsonObject.getString("drawingNo"));
                     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);
                  }
               }
            }
         }
      }
      //上传压缩包内的程序并更新程序文件地址
      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() && !NcProgramExportDNCService.isDataFile(entryName)) {
               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;
                  }
               }
            }
         }
      }
      return list;
      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);
         }
      }
   }
   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"));
   }
}