package org.springblade.mdm.machinefile.service; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; import org.springblade.core.log.exception.ServiceException; import org.springblade.mdm.basesetting.machine.service.MachineService; import org.springblade.mdm.basesetting.machine.entity.Machine; import org.springblade.mdm.commons.service.ParamService; import org.springblade.mdm.machinefile.entity.MachineFile; import org.springblade.mdm.program.service.ProgramAnnotationService; import org.springblade.mdm.program.service.programannotation.AnnotationUtil; import org.springblade.mdm.utils.FileContentUtil; 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 java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; 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; @Slf4j @Component public class MachineFileScanService { @Autowired private MachineFileService machineFileService; @Autowired private MachineService machineService; @Autowired private ParamService paramService; @Autowired private ProgramAnnotationService programAnnotationService; /** * 扫描所有机床的配置目录 */ @Async public void scanMachineFile() { List machines = machineService.getEnableMachines(); for (Machine machine : machines) { //扫描新文件 try { scanDir(machine,MachineFile.DIR_TYPE_REC); }catch(Exception e) { log.error("REC扫描文件异常,机床{}", machine.getCode(), e); } try { scanDir(machine,MachineFile.DIR_TYPE_SEND); }catch(Exception e) { log.error("SEND扫描文件异常,机床{}", machine.getCode(), e); } try { scanDir(machine,MachineFile.DIR_TYPE_TEMP); }catch(Exception e) { log.error("TEMP扫描文件异常,机床{}", machine.getCode(), e); } //清理数据库,删除文件不存在的数据 try { clearDeletedRecords(machine,MachineFile.DIR_TYPE_REC); }catch(Exception e) { log.error("REC扫描文件异常,机床{}", machine.getCode(), e); } try { clearDeletedRecords(machine,MachineFile.DIR_TYPE_SEND); }catch(Exception e) { log.error("SEND扫描文件异常,机床{}", machine.getCode(), e); } try { clearDeletedRecords(machine,MachineFile.DIR_TYPE_TEMP); }catch(Exception e) { log.error("TEMP扫描文件异常,机床{}", machine.getCode(), e); } } } /** * 扫描目录 * @param machine 机床信息 * @param dirType 目录类型 * @throws IOException */ public void scanDir(Machine machine,String dirType) throws IOException { String basePath = MachineFileService.getBasePath(machine,dirType); if(basePath == null) { log.warn("目录类型不匹配:{}",dirType); return; } Path dirPath = Paths.get(basePath); if(!dirPath.toFile().exists()){ log.warn("扫描目录:{} 不存在",dirPath); return; } // 只包含普通文件 List files = Files.list(dirPath) .filter(Files::isRegularFile).toList(); byte[] buffer = new byte[2048]; List annotatiionList = programAnnotationService.getAnnotionDictList(); //boolean exists;//文件是否存在于数据库中 for (Path filePath : files) { try { MachineFile mf = readFileToMachineFile(filePath,machine,dirType,annotatiionList); machineFileService.refreshFileData(mf); } catch (IOException e) { log.error("读取文件信息失败",e); } } } /** * 读取磁盘上的文件信息 * @param filePath 文件路径 * @param machine 机器 * @param dirType 目录类型 * @param annotatiionList 注解配置字典 用于读取程序状态 * @return MachineFile 实例 * @throws IOException */ public MachineFile readFileToMachineFile(Path filePath,Machine machine,String dirType,List annotatiionList) throws IOException { MachineFile mf = new MachineFile(); mf.setTenantId("000000"); mf.setName(filePath.toFile().getName()); mf.setDirType(dirType); mf.setMachineCode(machine.getCode()); mf.setProgramStatus(readProgramStatus(filePath,machine.getMachineGroupCode(),annotatiionList)); BasicFileAttributes attrs = Files.readAttributes( filePath, BasicFileAttributes.class ); FileTime creationTime = attrs.creationTime(); Date creationDate = new Date(creationTime.toMillis()); mf.setFileCreateTime(creationDate); FileTime modifyTime = attrs.lastModifiedTime(); mf.setFileModifyTime(new Date(modifyTime.toMillis())); mf.setFileSize(Files.size(filePath)); byte[] buffer = new byte[2048]; try (InputStream inputStream = Files.newInputStream(filePath)) { // 使用输入流读取文件内容 inputStream.read(buffer); mf.setMd5(DigestUtils.md5Hex(buffer)); } catch (IOException e) { log.error("读取文件md5失败",e); throw new ServiceException("读取文件md5失败"+e.getMessage()); } return mf; } /** * 读取文件中的程序状态 * @param filePath 文件路径 * @param controlSystem * @param annotatiionList 注释配置字典 * @return 状态的整数之和 * @throws IOException */ int readProgramStatus(Path filePath,String controlSystem,List annotatiionList) throws IOException { int programStatus = MachineFile.PROGRAM_STATUS_UNKNOWN; try(InputStream ins = Files.newInputStream(filePath); BufferedInputStream bis = new BufferedInputStream(ins)){ boolean isText= FileContentUtil.isTextFile(bis); if(!isText){ return MachineFile.PROGRAM_STATUS_UNKNOWN; } bis.reset(); String statusLine = FileContentUtil.readLineAt(ins,ProgramAnnotationService.STATUS_LINE_INDEX); if(AnnotationUtil.isAnnotation(statusLine,controlSystem,annotatiionList)){ String progStatusTxt = programAnnotationService.removeAnnotation(controlSystem,statusLine,annotatiionList); if(ProgramAnnotationService.SQ.equals(progStatusTxt)){ programStatus = MachineFile.PROGRAM_STATUS_TRY; }else if(ProgramAnnotationService.GH.equals(progStatusTxt)){ programStatus = MachineFile.PROGRAM_STATUS_CURED; }else if(ProgramAnnotationService.PL.equals(progStatusTxt)){ programStatus = MachineFile.PROGRAM_STATUS_DIVIASTION; } } } return programStatus; } /** * 清理已经删除了文件的记录 * @param machine * @param dirType * @throws IOException */ void clearDeletedRecords(Machine machine,String dirType) throws IOException { List machineFiles = this.machineFileService.lambdaQuery().eq(MachineFile::getDirType,dirType) .eq(MachineFile::getMachineCode,machine.getCode()).list(); String basePath = MachineFileService.getBasePath(machine,dirType); if(basePath == null) { log.warn("目录类型不匹配:{}",dirType); return; } Path dirPath = Paths.get(basePath); if(!dirPath.toFile().exists()){ log.warn("扫描目录:{} 不存在",dirPath); return; } List files = Files.list(dirPath) .filter(Files::isRegularFile).toList(); for(MachineFile mf : machineFiles){ long findCount = files.stream().filter(filePath -> filePath.toFile().getName().equals(mf.getName())).count(); if(findCount == 0){ //文件夹内没找到,需要删除记录 mf.markFileDeleted(); this.machineFileService.updateById(mf); } } } }