3、策略模式所需代码

2023-10-30 14:47:24 浏览数 (1)

1、策略接口上下文

代码语言:javascript复制
@Service
public class PathUploadStrategyContext {

        @Resource
        private Map<String, PathUploadStrategy> pathUploadStrategyMap;

        public void getFileInferStrategy(PathUpLoadMessage message, String strategy) throws IOException {
            pathUploadStrategyMap.get(IBaseEnum.getLabelByValue(strategy, PathUploadEnum.class)).upload(message,strategy);
        }

}

2、策略抽象实现类

代码语言:javascript复制
/**
 * 服务器路径上传文件
 *
 * @author Eliauk
 * @since 2023/9/28 15:16
 */
@Service
public abstract class AbstractPathUploadStrategyImpl implements PathUploadStrategy {




    private final Logger LOG = LoggerFactory.getLogger(AbstractPathUploadStrategyImpl.class);

    @Override
    public void upload(PathUpLoadMessage message, String strategy) throws IOException {
        LOG.info("开始执行{}服务器路径上传策略", strategy);

        if (exist(message)){

            LOG.info("档号为{}的档案已经存在,跳过上传",message.getFileName());
            return;
        }

        uploadByPath(message, strategy);

    }

    /**
     * 服务器路径上传抽象方法
     * @param message 队列消息
     * @param strategy 路径上传策略
     * @since 2023/9/28 15:16
     */
    abstract void uploadByPath(PathUpLoadMessage message, String strategy) throws IOException;

    /**
     * 判断当前任务是否已经上传抽象方法
     * @param message 队列消息
     * @return
     * true:已经上传
     * false:未上传
     * @since 2023/9/28 15:16
     */
    abstract boolean exist(PathUpLoadMessage message);

    protected List<File> getAllPDFFiles(File rootFolder, List<String> legalSuffix) {
        List<File> pdfFiles = new ArrayList<>();
        if (rootFolder.isDirectory()) {
            File[] fileList = rootFolder.listFiles();
            if (fileList != null) {
                for (File file : fileList) {
                    if (file.isDirectory()) {
                        pdfFiles.addAll(getAllPDFFiles(file, legalSuffix));
                    } else if (file.isFile() && legalSuffix.contains(getFileExtension(file)) && !file.getName().startsWith("._")) {
                        pdfFiles.add(file);
                    }
                }
            }
        }
        return pdfFiles;
    }

    /**
     * 获取文件的后缀名
     */
    private static String getFileExtension(File file) {
        String fileName = file.getName();
        int dotIndex = fileName.lastIndexOf(".");
        if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
            return fileName.substring(dotIndex   1).toLowerCase();
        }
        return "";
    }
}

3、策略枚举类

代码语言:javascript复制
/**
 * 服务器路径上传策略枚举
 *
 * @author Eliauk
 * @since 2023/9/28 14:32
 */
@Getter
@AllArgsConstructor
public enum PathUploadEnum implements IBaseEnum{

    VOLUME("案卷合并", "volumePathUploadStrategy"),

    PDF("PDF文件", "pdfPathUploadStrategy"),

    IMAGE_TO_PDF("合并图片文件","mergePicturePathUploadStrategy"),

    OFD("OFD文件", "ofdPathUploadStrategy");
    private final String value;
    private final String label;

    @Override
    public Object getValue() {
        return this.value;
    }

    @Override
    public String getLabel() {
        return this.label;
    }
}

4、实现类

1、 OdfPathUploadStrategyImpl

OFD转PDF工具源码

代码语言:javascript复制
/**
 * OFD文件服务器路径上传
 *
 * @author Eliauk
 * @since 2023/10/10 9:58
 */
@Service("ofdPathUploadStrategy")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OdfPathUploadStrategyImpl extends AbstractPathUploadStrategyImpl{

    private static Logger LOG = LoggerFactory.getLogger(OdfPathUploadStrategyImpl.class);
    private final AppraisalFileRepository appraisalFileRepository;

    private final AppraisalFileService appraisalFileService;

    private final IOssEndPoint ossEndPoint;


    @Override
    void uploadByPath(PathUpLoadMessage message, String strategy) throws IOException {

        // 接收所有包含pdf的文件夹
        final File file = new File(message.getFile());
        final String folderName = file.getName();
        // 拿到任务ID
        final Long taskId = Convert.toLong(message.getTaskId());
        // 拿到租户ID
        final String tenantId = message.getTenantId();
        // 是否覆盖
        final Boolean overWrite = Convert.toBool(message.getOverWrite());
        LOG.info("当前进行服务器路径上传OFD的文件夹是{}", folderName);
        final List<File> pdfFiles = getAllPDFFiles(file, List.of("ofd"));
        long timeStart = DateUtil.current();
        long countStart = DateUtil.current();
        LOG.info("开始解析文件夹{},包含{}个OFD文件", folderName, pdfFiles.size());

        for (int fileIndex = 0; fileIndex < pdfFiles.size(); fileIndex  ) {
            File ofdFile = pdfFiles.get(fileIndex);
            String fileName = ofdFile.getName();
            // 判断是否覆盖,如果覆盖就删除原文件,否则跳过
            List<AppraisalFile> existingFiles = appraisalFileRepository.findByTaskIdAndFileName(taskId, fileName);
            if (!existingFiles.isEmpty()) {
                if (overWrite) {
                    List<Long> existingIds = existingFiles.stream().map(AppraisalFile::getId).collect(Collectors.toList());
                    appraisalFileService.deleteExistingFiles(existingIds);
                } else {
                    LOG.info("已存在的文件将被跳过: {}", fileName);
                    continue;
                }
            }
            Attach ofdAttach = null;
            try {
                // 使用第一个 FileInputStream
                try (FileInputStream fileInputStream1 = new FileInputStream(ofdFile)) {
                    ofdAttach  = ossEndPoint.putAttachWithTenant(
                            new InMemoryMultipartFile(fileName, fileInputStream1),
                            tenantId
                    ).getData();
                }

                // 使用第二个 FileInputStream
                try (FileInputStream fileInputStream2 = new FileInputStream(ofdFile)) {
                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    ConvertHelper.toPdf(fileInputStream2, stream);
                    Attach pdfAttach = ossEndPoint.putAttach(new InMemoryMultipartFile(IdUtil.randomUUID()   ".pdf", stream.toByteArray())
                    ).getData();

                    AppraisalFile appraisalFile = appraisalFileService.createAppraisalFile(taskId, fileName, pdfAttach);
                    appraisalFile.setOfdAttach(ofdAttach.getId());
                    appraisalFile.setFileType(InferFileType.OFD);
                    appraisalFileRepository.save(appraisalFile);

                    LOG.info("上传OFD成功所在文件夹名称{} - 当前进度: {}/{},文件名: {},共已耗时: {}s",file.getName(),
                            fileIndex 1, pdfFiles.size(), fileName, (DateUtil.current() - timeStart) / 1000.0);
                }
            } catch (Exception e) {
                LOG.error("上传文件发生异常: {}", e.getMessage());
            }

        }
        LOG.info("上传OFD成功 - 总文件数: {},耗时: {}s", pdfFiles.size(), (DateUtil.current() - countStart) / 1000.0);

    }

    @Override
    boolean exist(PathUpLoadMessage message) {
        return Boolean.FALSE;
    }
}

2、VolumePathUploadStrategyImpl

代码语言:javascript复制
/**
 * 案卷合并服务器路径上传策略
 *
 * @author Eliauk
 * @since 2023/9/28 16:13
 */
@Service("volumePathUploadStrategy")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class VolumePathUploadStrategyImpl extends AbstractPathUploadStrategyImpl {

    private static Logger LOG = LoggerFactory.getLogger(VolumePathUploadStrategyImpl.class);
    private final AppraisalFileRepository appraisalFileRepository;

    private final AppraisalFileService appraisalFileService;

    private final IOssEndPoint ossEndPoint;

    @Override
    void uploadByPath(PathUpLoadMessage message, String strategy) throws IOException {


        final File uploadFileFolder = new File(message.getFile());
        final Long taskId = Convert.toLong(message.getTaskId());
        final String tenantId = message.getTenantId();
        final Boolean overWrite = Convert.toBool(message.getOverWrite());

        File[] imageFiles = uploadFileFolder.listFiles();

        // 创建一个Map来存储文件名前缀和相应的文件列表
        Map<String, List<File>> groupedFiles = new HashMap<>();
        for (File imageFile : imageFiles) {
            String name = imageFile.getName();
            String prefix = name.substring(0, name.lastIndexOf('-')); // 假设前缀是直到最后一个'-'符号
            groupedFiles.computeIfAbsent(prefix, k -> new ArrayList<>()).add(imageFile);
        }

        LOG.info("开始处理文件夹名称为{}的文件夹,里边最终会合并成{}个文件",uploadFileFolder.getName(),groupedFiles.size());

        int pdfNum = 0;
        for (Map.Entry<String, List<File>> entry : groupedFiles.entrySet()) {
            String prefix = entry.getKey();
            List<File> filesInGroup = entry.getValue();

            String folderName = prefix;  // 你可以根据需要修改
            String fileName = folderName   ".pdf";
            //pathUpLoadProducer.syncSendPathUpload(tenantId,Convert.toStr(taskId),fileName,Convert.toStr(uploadFileFolder),Convert.toStr(overWrite),PathUploadType.PDF);
            // 判断是否覆盖已存在的文件
            List<AppraisalFile> existingFiles = appraisalFileRepository.findByTaskIdAndFileName(taskId, fileName);
            if (existingFiles.size() > 0) {
                if (overWrite) {
                    List<Long> existingFileIds = existingFiles.stream().map(AppraisalFile::getId).collect(Collectors.toList());
                    appraisalFileService.deleteExistingFiles(existingFileIds);
                } else {
                    LOG.info("跳过已存在的文件");
                    pdfNum  ;
                    continue;
                }
            }

            List<byte[]> images = filesInGroup.stream()
                    .filter(File::isFile)
                    .map(imageFile -> {
                        try (InputStream fileInputStream = new FileInputStream(imageFile)) {
                            return IOUtils.toByteArray(fileInputStream);
                        } catch (IOException e) {
                            e.printStackTrace();
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            if (images.isEmpty()) {
                pdfNum  ;
                LOG.info("跳过空文件夹");
                continue;
            }

            final byte[] bytes = appraisalFileService.convertToPdf(images);

            byte[] modifiedPdfData= null;
            try (PDDocument document = PDDocument.load(bytes)) {
                int lastPageNumber = document.getNumberOfPages();

                // 删除最后一页
                document.removePage(lastPageNumber - 1);

                // 保存修改后的PDF
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                document.save(outputStream);
                modifiedPdfData = outputStream.toByteArray();


            } catch (IOException e) {
                // 处理PDF操作异常
                e.printStackTrace();
            }
            Attach pdfAttach = ossEndPoint.putAttachWithTenant(
                    new InMemoryMultipartFile(fileName, new ByteArrayInputStream(modifiedPdfData)),
                    tenantId
            ).getData();

            AppraisalFile appraisalFile = appraisalFileService.createAppraisalFile(taskId, fileName, pdfAttach);
            appraisalFileRepository.save(appraisalFile);

            pdfNum  ;
            LOG.info("合并处理文件夹名称为{}的PDF成功,当前进度:{}/{},当前文件名:{},共{}页",
                    folderName,  pdfNum, groupedFiles.size(), folderName, images.size());
        }

    }

    @Override
    boolean exist(PathUpLoadMessage message) {
        return Boolean.FALSE;

    }


}

3、MergePicturePathUploadStrategyImpl

代码语言:javascript复制
/**
 * 合并图片文件服务器路径上传策略
 *
 * @author Eliauk
 * @since 2023/10/7 16:32
 */
@Service("mergePicturePathUploadStrategy")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MergePicturePathUploadStrategyImpl extends AbstractPathUploadStrategyImpl {

    private static Logger LOG = LoggerFactory.getLogger(MergePicturePathUploadStrategyImpl.class);
    private final AppraisalFileRepository appraisalFileRepository;

    private final AppraisalFileService appraisalFileService;

    private final IOssEndPoint ossEndPoint;

    @Override
    void uploadByPath(PathUpLoadMessage message, String strategy) throws IOException {

        // 接收所有包含pdf的文件夹
        final File file = new File(message.getFile());
        final String folderName = file.getName();
        // 拿到任务ID
        final Long taskId = Convert.toLong(message.getTaskId());
        // 拿到租户ID
        final String tenantId = message.getTenantId();
        // 是否覆盖
        final Boolean overWrite = Convert.toBool(message.getOverWrite());
        LOG.info("当前进行服务器路径上传进行合并图片文件的文件夹是{}", folderName);

        final File[] imageFiles = file.listFiles();
        if (ObjectUtil.isNotEmpty(imageFiles)) {
            Arrays.sort(imageFiles, Comparator.comparing(File::getName));
        }

        String fileName = folderName   ".pdf";

        // 判断是否覆盖已存在的文件
        List<AppraisalFile> existingFiles = appraisalFileRepository.findByTaskIdAndFileName(taskId, fileName);
        if (!existingFiles.isEmpty()) {
            if (overWrite) {
                List<Long> existingFileIds = existingFiles.stream().map(AppraisalFile::getId).collect(Collectors.toList());
                appraisalFileService.deleteExistingFiles(existingFileIds);
            } else {
                LOG.info("跳过已存在的文件");
                return;
            }
        }


        if (ObjectUtil.isNotEmpty(imageFiles)) {
            Arrays.sort(imageFiles, Comparator.comparing(File::getName));
        }

        List<byte[]> images = Arrays.stream(imageFiles)
                .filter(File::isFile)
                .map(imageFile -> {
                    try (InputStream fileInputStream = new FileInputStream(imageFile)) {
                        return IOUtils.toByteArray(fileInputStream);
                    } catch (IOException e) {
                        e.printStackTrace();
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (images.isEmpty()) {

            LOG.info("跳过空文件夹");
            return;
        }

        final byte[] bytes = appraisalFileService.convertToPdf(images);

        byte[] modifiedPdfData= null;
        try (PDDocument document = PDDocument.load(bytes)) {
            int lastPageNumber = document.getNumberOfPages();

            // 删除最后一页
            document.removePage(lastPageNumber - 1);

            // 保存修改后的PDF
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            document.save(outputStream);
            modifiedPdfData = outputStream.toByteArray();

        } catch (IOException e) {
            // 处理PDF操作异常
            e.printStackTrace();
        }
        Attach pdfAttach = ossEndPoint.putAttachWithTenant(
                new InMemoryMultipartFile(fileName, new ByteArrayInputStream(modifiedPdfData)),
                tenantId
        ).getData();

        AppraisalFile appraisalFile = appraisalFileService.createAppraisalFile(taskId, fileName, pdfAttach);
        appraisalFileRepository.save(appraisalFile);

        LOG.info("当前文件夹名称为{},当前文件名:{},共{}页", folderName ,fileName, images.size());


    }

    @Override
    boolean exist(PathUpLoadMessage message) {
        return Boolean.FALSE;
    }
}

0 人点赞