package org.springblade.mdm.machinefile.service; import com.qiniu.util.IOUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.tool.utils.Func; import org.springblade.mdm.basesetting.machine.entity.Machine; import org.springblade.mdm.basesetting.machine.service.MachineService; import org.springblade.mdm.commons.contants.RegExpConstants; import org.springblade.mdm.commons.service.ParamService; import org.springblade.mdm.gkw.programnode.vo.ProgramNameVO; import org.springblade.mdm.machinefile.entity.FileSendRecord; import org.springblade.mdm.machinefile.entity.MachineFile; import org.springblade.mdm.program.entity.ProgramOnMachine; import org.springblade.mdm.program.service.ProgramAnnotationService; import org.springblade.mdm.program.service.ProgramOnMachineService; import org.springblade.mdm.program.service.programannotation.*; 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.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; import java.util.Date; import java.util.List; import java.util.Optional; import java.util.regex.Matcher; @Slf4j @Component public class ReceiveFileCheckService { @Autowired private MachineFileService machineFileService; @Autowired private MachineService machineService; @Autowired private ProgramOnMachineService programOnMachineService; @Autowired private FileSendRecordService fileSendRecordService; @Autowired private AnnotationProcessorHelper annoProcessHelper; @Autowired private ProgramAnnotationService programAnnotationService; /** * 文件合法性检查 * @param machineFile */ @Transactional(rollbackFor = Exception.class) public void check(MachineFile machineFile,List allFilesInDir,Machine machine) throws IOException { String srcFilepath = MachineFileService.getBasePath(machine,machineFile.getDirType())+ File.separator+machineFile.getName(); log.info("开始检查文件{}",srcFilepath); Path checkFilePath = Paths.get(srcFilepath); if(!checkFilePath.toFile().exists()){ return; } AnnotationProperties annoProps = AnnotationProperties.getDefault(); try(InputStream fileIns = Files.newInputStream(checkFilePath);) { int excepType = MachineFile.EXCEPTION_OK; ByteArrayInputStream byteStream = new ByteArrayInputStream(IOUtils.toByteArray(fileIns)); if(!FileContentUtil.isTextFile(byteStream)){ //非文本 excepType = MachineFile.EXCEPTION_NOT_TEXT; }else{ //Matcher matcher = RegExpConstants.PROGRAM_FILE_PATTERN.matcher(machineFile.getName()); ProgramNameVO progNameVO = ProgramFileNameParser.parseProgramName(machineFile.getName()); boolean filenameValid = progNameVO.isValidFilename(); if(!filenameValid){ excepType = MachineFile.EXCEPTION_BAD_FILENAME; }else { String prefix = progNameVO.logicProgramName()+"-"; long matchCount = allFilesInDir.stream().filter(file -> file.getName().startsWith(prefix)).count(); if(matchCount != progNameVO.getSegmentCount()){//文件段数缺失 excepType = MachineFile.EXCEPTION_LOST_FILES; }else{ //检查是否匹配下发记录的段数 //正负3秒作为查询时间 Date beginTime = new Date(machineFile.getFileCreateTime().getTime()-3000); Date endTime = new Date(machineFile.getFileCreateTime().getTime()+3000); Optional optFile = fileSendRecordService.lambdaQuery() .eq(FileSendRecord::getMachineCode,machineFile.getMachineCode()) .likeRight(FileSendRecord::getName,prefix).between(FileSendRecord::getCreateTime,beginTime,endTime).oneOpt(); boolean matchSendRecord;//文件是否有下发记录 if(optFile.isPresent()){ matchSendRecord = true; //确实下发过,比对总段数是否相同 FileSendRecord sendFile = optFile.get(); ProgramNameVO sendProgNameVO = ProgramFileNameParser.parseProgramName(sendFile.getName()); if(progNameVO.getSegmentCount() != sendProgNameVO.getSegmentCount()){ //段数不匹配下发记录 excepType = MachineFile.EXCEPTION_NOT_MATCH_SEND_SEG_COUNT; }else if(!StringUtils.equals(sendProgNameVO.getLgPart(),progNameVO.getLgPart())){ excepType = MachineFile.EXCEPTION_NOT_MATCH_SEND_LG; } }else{ matchSendRecord = false; } if(!matchSendRecord){//如果文件未下发过,查看是否有现场编程记录 byteStream.reset(); //TODO 下面这些应该都没有,因为时现场编程 String planStatusLine = AnnotationUtil.removeAnnotation(machine.getControlSystem(),FileContentUtil.readLineAt(byteStream,annoProps.getStatusLineIndex()),programAnnotationService.getAnnotionDictList()); String lgNo;//更改单号 if(AnnotationUtil.LG.equals(planStatusLine)) {//是更改单 String lgLine = FileContentUtil.readLineAt(byteStream, annoProps.getDeviationLineIndex()); lgNo = AnnotationUtil.removeAnnotation(machine.getControlSystem(), lgLine, programAnnotationService.getAnnotionDictList()); }else{ lgNo = null; } long progOnMachineCount = programOnMachineService.lambdaQuery() .eq(ProgramOnMachine::getDrawingNo,progNameVO.getDrawingNo()) .eq(ProgramOnMachine::getProcessNo,progNameVO.getProcessNo()) .eq(ProgramOnMachine::getProcessEdition,progNameVO.getProcessEdition()) .eq(lgNo != null,ProgramOnMachine::getDeviation,lgNo)//TODO 临时更改单序号匹配 .eq(ProgramOnMachine::getMachineCode,machineFile.getMachineCode()).count(); if(progOnMachineCount == 0){//无现场编程记录 excepType = MachineFile.EXCEPTION_NOT_MATCH_RECORD; } } } } } machineFile.setExceptionType(excepType); log.info("检查文件结束{}",srcFilepath); machineFileService.updateById(machineFile); } } }