package com.gz.scheduled; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import com.gz.config.MountArchiveFileConfig; import com.gz.core.exception.BusinessException; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Profile; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.io.File; import java.util.Set; /** * 扫描档案文件定时任务 * * @author LiuchangLan * @date 2021/3/16 13:36 */ @Slf4j @Component @Profile("prod") public class ScanArchiveFileScheduled { @Resource private StringRedisTemplate stringRedisTemplate; /** * @description 递归扫描文件夹 pdf、tif 文件放入队列 其他文件、空文件夹删除处理 * @author LiuChangLan * @since 2021/3/23 15:52 */ private void sendFileToQUeue(File directory) throws InterruptedException { if (directory.isDirectory()) { // 获取文件夹下的所有文件 File[] files = directory.listFiles(); // 文件夹为空、非扫描根目录、文件夹不在运行 删除目录 if (files.length == 0 && !directory.getPath().equals(MountArchiveFileConfig.SCAN_BASE_PATH)) { FileUtil.del(directory); log.info("文件夹{}为空,自动删除", directory.getPath()); } for (File file : files) { if (file.isDirectory()) { // 扫描到文件夹 递归 sendFileToQUeue(file); } else { // 等待处理中 跳过 处理错误 跳过 if (MountArchiveFileConfig.WAIT_HANDLE_FILE.containsKey(file.getPath())) { log.info("文件[{}]待处理 跳过待处理文件", file.getPath()); continue; } if (stringRedisTemplate.hasKey(String.format(MountArchiveFileConfig.ARCHIVE_FILE_MOUNT_ERROR_FOMAT, file.getName()))) { log.info("文件[{}]处理错误 跳过处理错误文件", file.getPath()); continue; } // pdf 文件 if ("pdf".equals(FileUtil.getType(file))) { MountArchiveFileConfig.WAIT_HANDLE_FILE.put(file.getPath(), file); MountArchiveFileConfig.PDF_QUEUE.put(file); log.info("扫描到pdf文件,当前队列还剩余{}个", MountArchiveFileConfig.PDF_QUEUE.size()); // tif 文件 } else if ("tif".equals(FileUtil.getType(file))) { MountArchiveFileConfig.WAIT_HANDLE_FILE.put(file.getPath(), file); MountArchiveFileConfig.TIF_QUEUE.put(file); log.info("扫描到tif文件,当前队列还剩余{}个", MountArchiveFileConfig.TIF_QUEUE.size()); } else { FileUtil.del(file); log.info("扫描到其他类型文件,删除文件[{}]", file); } } } } else { throw new BusinessException(500, "入参非路径"); } } /** * @description 扫描根目录下的文件 进行入队 * @author LiuChangLan * @since 2021/3/17 14:16 */ @Scheduled(cron = "0/30 * * * * ?") public void startScan() throws InterruptedException { if (Boolean.parseBoolean(stringRedisTemplate.opsForValue().get(MountArchiveFileConfig.FILE_RUNNING))){ log.warn("文件传输中 跳过扫描"); return; } if (StrUtil.isEmpty(MountArchiveFileConfig.SCAN_BASE_PATH)) { log.warn("未配置扫描根目录 跳过扫描"); return; } log.debug("开始扫描[{}]下的档案文件", MountArchiveFileConfig.SCAN_BASE_PATH); File scanPath = new File(MountArchiveFileConfig.SCAN_BASE_PATH); if (!scanPath.exists()) { throw new BusinessException(500, "档案根目录不存在,无法扫描"); } this.sendFileToQUeue(scanPath); } /** * @description 挂载错误 定时重新入队 * @author LiuChangLan * @since 2021/3/17 14:15 */ @Scheduled(cron = "0 0 1 * * ?") // @Scheduled(cron = "0/30 * * * * ?") public void errorRejoinQueue() throws InterruptedException { log.debug("开始读取错误队列,重新放入队列进行挂载"); Set keys = stringRedisTemplate.keys(String.format(MountArchiveFileConfig.ARCHIVE_FILE_MOUNT_ERROR_FOMAT, "*")); for (String key : keys) { String pdfPath = stringRedisTemplate.opsForHash().get(key, MountArchiveFileConfig.ERROR_FILE_PATH_KEY).toString(); MountArchiveFileConfig.PDF_QUEUE.put(new File(pdfPath)); log.debug("错误文件:[{}]重新入队", pdfPath); stringRedisTemplate.delete(key); } } }